﻿#ifndef __SBMATH_H__
#define __SBMATH_H__

#if _MSC_VER
#pragma once
#pragma warning(push)
#pragma warning(disable:4201)
#endif

#include <math.h>
#include "sbcs.h"

K_EXTERN_C_BEGIN

//////////////////////////////////////////////////////////////////////////
// constant
#define KM_EPSILON							0.0001f
#define KM_PI								3.1415926535897932384626433832795028841971693993751f
#define KM_PI_2								6.2831853071795864769252867665590057683943387987502f
#define KM_PI_HALF							1.5707963267948966192313216916397514420985846996876f
#define KM_PI_HOH							0.7853981633974483096156608458198757210492923498438f
#define KM_RAD_DEG							(180.0f/KM_PI)
#define KM_DEG_RAD							(KM_PI/180.0f)

#define KM_E								2.7182818284590452353602874713526624977572470937000f
#define KM_LOG2E							1.44269504088896340736f
#define KM_LOG10E							0.43429448190325182765f
#define KM_LOG2B10							0.30102999566398119521f
#define KM_LN2								0.6931471805599453094172321214581765680755001343603f
#define KM_LN10								2.3025850929940456840179914546843642076011014886288f
#define KM_SQRT2							1.4142135623730950488016887242096980785696718753769f
#define KM_SQRT_HALF						0.7071067811865475244008443621048490392848359376884f


//////////////////////////////////////////////////////////////////////////
// macro maths
#define k_tan(f)							(float)(tanf((float)(f)))
#define k_tanh(f)							(float)(tanhf((float)(f)))
#define k_sin(f)							(float)(sinf((float)(f)))
#define k_cos(f)							(float)(cosf((float)(f)))
#define k_cosh(f)							(float)(coshf((float)(f)))
#define k_exp(f)							(float)(expf((float)(f)))
#define k_log(f)							(float)(logf((float)(f)))
#define k_log10(f)							(float)(log10f((float)(f)))
#define k_sqrt(f)							(float)(sqrtf((float)(f)))
#define k_acos(f)							(float)(acosf((float)(f)))
#define k_asin(f)							(float)(asinf((float)(f)))
#define k_atan2(x,y)						(float)(atan2f((float)(x),(float)(y)))
#define k_atan(f)							(float)(atanf((float)(f)))
#define k_pow(f,p)							(float)(powf((float)(f),(float)(p)))
#define k_mod(f,d)							(float)(fmodf((float)(f),(float)(d)))
#define k_abs(f)							(float)(fabsf((float)(f)))
#define k_ceil(f)							(float)(ceilf((float)(f)))
#define k_floor(f)							(float)(floorf((float)(f)))
#define k_fract(f)							((f)-k_floor(f))
#define k_rint(f)							(float)(floorf((float)((f)+0.5)))
#define k_positive(f)						((f)>=0.0f)
#define k_negative(f)						((f)<0.0f)
#define k_sgeq(a,b)							((a)<0.0f && (b)<0.0f)
#define k_torad(d)							(float)(((float)(d))*KM_DEG_RAD)
#define k_todeg(r)							(float)(((float)(r))*KM_RAD_DEG)
#define k_eq(a,b)							(((a)+KM_EPSILON>(b)) && ((a)-KM_EPSILON<(b)))
#define k_epsilon(a,b,e)					(((a)+(e)>(b)) && ((a)-(e)<(b)))

K_INLINE float k_max(float a, float b) { return K_MAX(a, b); }
K_INLINE float k_min(float a, float b) { return K_MIN(a, b); }
K_INLINE float k_clamp(float f, float min, float max) { return K_CLAMP(f, min, max); }
K_INLINE float k_cprad(float f) { return (f < -KM_PI_2) ? f + KM_PI_2 : (f > KM_PI_2) ? f - KM_PI_2 : f; }
K_INLINE float k_lerp(float l, float r, float f) { return l + f * (r - l); }
K_INLINE void k_swap(float* l, float *r) { float t = *l; *l = *r; *r = t; }
K_INLINE void k_swapi(kint* l, kint *r) { kint t = *l; *l = *r; *r = t; }

KAPI void k_sincos(float f, float* s, float* c);


//////////////////////////////////////////////////////////////////////////
// random

// mersenne twister
typedef struct kMrsn   kMrsn;
typedef struct kMrsn   kMtRand;

// nans
KAPI void k_snans(kuint* seed, kuint genseed, kcham addtip);
KAPI kint k_nans(kuint* seed);
KAPI kint k_nans_value(kuint* seed);
KAPI kint k_nans_int(kuint* seed, kint min, kint max);
KAPI klong k_nans_long(kuint* seed, klong min, klong max);
KAPI kuint k_nans_uint(kuint* seed, kuint min, kuint max);
KAPI kulong k_nans_ulong(kuint* seed, kulong min, kulong max);
KAPI float k_nans_single(kuint* seed, float min, float max);
KAPI double k_nans_double(kuint* seed, double min, double max);

// randomize
KAPI void k_srand(kuint seed);
KAPI kint k_rand(void);
KAPI kint k_rand_value(void);
KAPI kint k_rand_int(kint min, kint max);
KAPI klong k_rand_long(klong min, klong max);
KAPI kuint k_rand_uint(kuint min, kuint max);
KAPI kulong k_rand_ulong(kulong min, kulong max);
KAPI float k_rand_single(float min, float max);
KAPI double k_rand_double(double min, double max);

// mersenne twister
KAPI kMrsn* k_mrsn_alloc(void);
KAPI void k_mrsn_seed(kMrsn* self, kuint seed);
KAPI kuint k_mrsn_uint(kMrsn* self);
KAPI kulong k_mrsn_ulong(kMrsn* self);

KAPI double k_mrsn_open_open(kMrsn* self);
KAPI double k_mrsn_close_close(kMrsn* self);
KAPI double k_mrsn_rand53(kMrsn* self);

// mersenne twister, using math
KAPI double k_mrsn_gaussian(kMrsn* self, double mn, double sd);


//////////////////////////////////////////////////////////////////////////
// type declaration

// vector2
typedef struct kVec2
{
	union
	{
		struct { float x, y; };
		struct { float u, v; };
		struct { float min, max; };
		struct { float width, height; };
	};
} kVec2;

// vector3
typedef struct kVec3
{
	union
	{
		struct { float x, y, z; };
		struct { float a, b, c; };
	};
} kVec3;

// vector4
typedef struct kVec4
{
	union
	{
		struct { float x, y, z, w; };
		struct { float a, b, c, d; };
	};
} kVec4;

// quaternion
typedef struct kQuat
{
	float x, y, z, w;
} kQuat;

// matrix
typedef struct kMat4
{
	union
	{
		struct
		{
			float _11, _12, _13, _14;
			float _21, _22, _23, _24;
			float _31, _32, _33, _34;
			float _41, _42, _43, _44;
		};
		float m[4][4];
		float _m[16];
#if defined(_INCLUDED_MM2) && defined(SB_MM2)
		__m128 m128[4];
#endif
	};
} kMat4;

// point
typedef struct kPt
{
	union
	{
		struct { kint x, y; };
		struct { kint min, max; };
		struct { kint left, right; };
		struct { kuint ux, uy; };
		struct { kuint umin, umax; };
		struct { kuint uleft, uright; };
		struct { kuint width, height; };
	};
} kPt;

// rect
typedef struct kRt
{
	kint left, top, right, bottom;
} kRt;

// quad
typedef struct kQd
{
	float left, top, right, bottom;
} kQd;

// color
typedef struct kCr
{
	float r, g, b, a;
} kCr;

// uni color
typedef struct kCu
{
	kbyte b, g, r, a;
} kCu;

// uni color for uint
typedef union kUcu
{
	kuint	v;
	kCu		cu;
} kUcu;

// plane
typedef struct kPln
{
	float a, b, c, d;
} kPln;

// line 3
typedef struct kLn3
{
	kVec3 begin, end;
} kLn3;

// transform
typedef struct kTrfm
{
	kVec3 loc;
	kQuat rot;
	kVec3 scl;
} kTrfm;

// vector half 2
typedef struct kVecH2
{
	khalf x, y;
} kVecH2;

// vector half 3
typedef struct kVecH3
{
	khalf x, y, z;
} kVecH3;

// vector half 4
typedef struct kVecH4
{
	khalf x, y, z, w;
} kVecH4;

// location & size
typedef struct kLsN
{
	kint loc;
	kint siz;
} kLsN;

// location & size float type
typedef struct kLsF
{
	float loc;
	float size;
} kLsF;





















//////////////////////////////////////////////////////////////////////////
// type implement

// vector 2
KAPI void k_vec2_norm(kVec2* pv, const kVec2* v);
KAPI void k_vec2_bary_centric(kVec2* pv, const kVec2* v1, const kVec2* v2, const kVec2* v3, float f, float g);
KAPI void k_vec2_catmull_rom(kVec2* pv, const kVec2* v0, const kVec2* v1, const kVec2* v2, const kVec2* v3, float s);
KAPI void k_vec2_hermite(kVec2* pv, const kVec2* v1, const kVec2* t1, const kVec2* v2, const kVec2* t2, float s);

K_INLINE void k_vec2_set(kVec2* pv, float x, float y)
{
	pv->x = x;
	pv->y = y;
}

K_INLINE void k_vec2_identify(kVec2* pv)
{
	pv->x = 0.0f;
	pv->y = 0.0f;
}

K_INLINE void k_vec2_diag(kVec2* pv, float v)
{
	pv->x = v;
	pv->y = v;
}

K_INLINE void k_vec2_add(kVec2* pv, const kVec2* left, const kVec2* right)
{
	pv->x = left->x + right->x;
	pv->y = left->y + right->y;
}

K_INLINE void k_vec2_sub(kVec2* pv, const kVec2* left, const kVec2* right)
{
	pv->x = left->x - right->x;
	pv->y = left->y - right->y;
}

K_INLINE void k_vec2_mag(kVec2* pv, const kVec2* left, float right)
{
	pv->x = left->x * right;
	pv->y = left->y * right;
}

K_INLINE void k_vec2_inc(kVec2* pv, float f)
{
	pv->x += f;
	pv->y += f;
}

K_INLINE void k_vec2_dec(kVec2* pv, float f)
{
	pv->x -= f;
	pv->y -= f;
}

K_INLINE void k_vec2_abs(kVec2* pv, const kVec2* v)
{
	pv->x = k_abs(v->x);
	pv->y = k_abs(v->y);
}

K_INLINE float k_vec2_accum(const kVec2* pv, float s)
{
	return (pv->x + pv->y) * s;
}

K_INLINE void k_vec2_cross(kVec2* pv, const kVec2* left, const kVec2* right)
{
	k_vec2_set(pv,
		left->y * right->x - left->x * right->y,
		left->x * right->y - left->y * right->x);
}

K_INLINE void k_vec2_invert(kVec2* pv, const kVec2* v)  // invert
{
	pv->x = -v->x;
	pv->y = -v->y;
}

K_INLINE void k_vec2_neg(kVec2* pv, const kVec2* v)
{
	pv->x = 1.0f - v->x;
	pv->y = 1.0f - v->y;
}

K_INLINE float k_vec2_dot(const kVec2* left, const kVec2* right)
{
	return left->x * right->x + left->y * right->y;
}

K_INLINE float k_vec2_len_sq(const kVec2* pv)
{
	return pv->x * pv->x + pv->y * pv->y;
}

K_INLINE float k_vec2_len(const kVec2* pv)
{
	return k_sqrt(k_vec2_len_sq(pv));
}

K_INLINE void k_vec2_interpolate(kVec2* pv, const kVec2* left, const kVec2* right, float s)
{
	float f = 1.0f - s;
	pv->x = right->x * f + left->x * s;
	pv->y = right->y * f + left->y * s;
}

K_INLINE void k_vec2_lerp(kVec2* pv, const kVec2* left, const kVec2* right, float s)
{
	pv->x = left->x + s * (right->x - left->x);
	pv->y = left->y + s * (right->y - left->y);
}

K_INLINE void k_vec2_min(kVec2* pv, const kVec2* left, const kVec2* right)
{
	pv->x = (left->x < right->x) ? left->x : right->x;
	pv->y = (left->y < right->y) ? left->y : right->y;
}

K_INLINE void k_vec2_max(kVec2* pv, const kVec2* left, const kVec2* right)
{
	pv->x = (left->x > right->x) ? left->x : right->x;
	pv->y = (left->y > right->y) ? left->y : right->y;
}

K_INLINE kcham k_vec2_eq(const kVec2* left, const kVec2* right)
{
	return
		k_eq(left->x, right->x) &&
		k_eq(left->y, right->y);
}

K_INLINE kcham k_vec2_epsilon(const kVec2* left, const kVec2* right, float e)
{
	return
		k_epsilon(left->x, right->x, e) &&
		k_epsilon(left->y, right->y, e);
}

K_INLINE kcham k_vec2_isidentify(const kVec2* pv)
{
	return k_eq(pv->x, 0.0f) && k_eq(pv->y, 0.0f);
}

// vector 3
KAPI void k_vec3_norm(kVec3* pv, const kVec3* v);
KAPI void k_vec3_interpolate(kVec3* pv, const kVec3* left, const kVec3* right, float s);
KAPI void k_vec3_lerp(kVec3* pv, const kVec3* left, const kVec3* right, float s);
KAPI void k_vec3_lerp_len(kVec3* pv, const kVec3* left, const kVec3* right, float s, float l);
KAPI void k_vec3_rot_quat(kVec3* pv, const kQuat* q);
KAPI void k_vec3_rot_mat4(kVec3* pv, const kMat4* m);
KAPI void k_vec3_rot_quat_vec3(kVec3* pv, const kQuat* q, const kVec3* v);
KAPI void k_vec3_bary_centric(kVec3* pv, const kVec3* v1, const kVec3* v2, const kVec3* v3, float f, float g);
KAPI void k_vec3_catmull_rom(kVec3* pv, const kVec3* v0, const kVec3* v1, const kVec3* v2, const kVec3* v3, float s);
KAPI void k_vec3_hermite(kVec3* pv, const kVec3* v1, const kVec3* t1, const kVec3* v2, const kVec3* t2, float s);
KAPI void k_vec3_form_norm(kVec3* pv, const kVec3* v0, const kVec3* v1, const kVec3* v2);
KAPI float k_vec3_yaw(const kVec3* pv);
KAPI kcham k_vec3_reflect(kVec3* pv, const kVec3* in, const kVec3* dir);
KAPI kcham k_vec3_between(const kVec3* p, const kVec3* b, const kVec3* e);
KAPI kcham k_vec3_intersect_line(kVec3* pv, const kPln* pl, const kVec3* loc, const kVec3* dir);
KAPI kcham k_vec3_intersect_pt(kVec3* pv, const kPln* pl, const kVec3* v1, const kVec3* v2);
KAPI kcham k_vec3_intersect_between_pt(kVec3* pv, const kPln* pl, const kVec3* v1, const kVec3* v2);
KAPI kcham k_vec3_intersect_planes(kVec3* pv, const kPln* pl, const kPln* o1, const kPln* o2);
KAPI void k_vec3_cpt_line(kVec3* pv, const kLn3* l, const kVec3* v);

K_INLINE void k_vec3_set(kVec3* pv, float x, float y, float z)
{
	pv->x = x;
	pv->y = y;
	pv->z = z;
}

K_INLINE void k_vec3_identify(kVec3* pv)
{
	pv->x = 0.0f;
	pv->y = 0.0f;
	pv->z = 0.0f;
}

K_INLINE void k_vec3_diag(kVec3* pv, float v)
{
	pv->x = v;
	pv->y = v;
	pv->z = v;
}

K_INLINE void k_vec3_add(kVec3* pv, const kVec3* left, const kVec3* right)
{
	pv->x = left->x + right->x;
	pv->y = left->y + right->y;
	pv->z = left->z + right->z;
}

K_INLINE void k_vec3_sub(kVec3* pv, const kVec3* left, const kVec3* right)
{
	pv->x = left->x - right->x;
	pv->y = left->y - right->y;
	pv->z = left->z - right->z;
}

K_INLINE void k_vec3_mag(kVec3* pv, const kVec3* left, float right)
{
	pv->x = left->x * right;
	pv->y = left->y * right;
	pv->z = left->z * right;
}

K_INLINE void k_vec3_inc(kVec3* pv, float f)
{
	pv->x += f;
	pv->y += f;
	pv->z += f;
}

K_INLINE void k_vec3_dec(kVec3* pv, float f)
{
	pv->x -= f;
	pv->y -= f;
	pv->z -= f;
}

K_INLINE void k_vec3_abs(kVec3* pv, const kVec3* v)
{
	pv->x = k_abs(v->x);
	pv->y = k_abs(v->y);
	pv->z = k_abs(v->z);
}

K_INLINE float k_vec3_accum(const kVec3* pv, float s)
{
	return (pv->x + pv->y + pv->z) * s;
}

K_INLINE void k_vec3_cross(kVec3* pv, const kVec3* left, const kVec3* right)
{
	k_vec3_set(pv,
		left->y * right->z - left->z * right->y,
		left->z * right->x - left->x * right->z,
		left->x * right->y - left->y * right->x);
}

K_INLINE void k_vec3_invert(kVec3* pv, const kVec3* v)  // invert
{
	pv->x = -v->x;
	pv->y = -v->y;
	pv->z = -v->z;
}

K_INLINE void k_vec3_neg(kVec3* pv, const kVec3* v)
{
	pv->x = 1.0f - v->x;
	pv->y = 1.0f - v->y;
	pv->z = 1.0f - v->z;
}

K_INLINE float k_vec3_dot(const kVec3* left, const kVec3* right)
{
	return left->x * right->x + left->y * right->y + left->z * right->z;
}

K_INLINE float k_vec3_len_sq(const kVec3* pv)
{
	return pv->x * pv->x + pv->y * pv->y + pv->z * pv->z;
}

K_INLINE float k_vec3_len(const kVec3* pv)
{
	return k_sqrt(k_vec3_len_sq(pv));
}


K_INLINE void k_vec3_min(kVec3* pv, const kVec3* left, const kVec3* right)
{
	pv->x = (left->x < right->x) ? left->x : right->x;
	pv->y = (left->y < right->y) ? left->y : right->y;
	pv->z = (left->z < right->z) ? left->z : right->z;
}

K_INLINE void k_vec3_max(kVec3* pv, const kVec3* left, const kVec3* right)
{
	pv->x = (left->x > right->x) ? left->x : right->x;
	pv->y = (left->y > right->y) ? left->y : right->y;
	pv->z = (left->z > right->z) ? left->z : right->z;
}

K_INLINE void k_vec3_selfmin(kVec3* pv, const kVec3* t)
{
	if (pv->x > t->x)
		pv->x = t->x;

	if (pv->y > t->y)
		pv->y = t->y;

	if (pv->z > t->z)
		pv->z = t->z;
}

K_INLINE void k_vec3_selfmax(kVec3* pv, const kVec3* t)
{
	if (pv->x < t->x)
		pv->x = t->x;

	if (pv->y < t->y)
		pv->y = t->y;

	if (pv->z < t->z)
		pv->z = t->z;
}

K_INLINE kcham k_vec3_eq(const kVec3* left, const kVec3* right)
{
	return
		k_eq(left->x, right->x) &&
		k_eq(left->y, right->y) &&
		k_eq(left->z, right->z);
}

K_INLINE kcham k_vec3_epsilon(const kVec3* left, const kVec3* right, float e)
{
	return
		k_epsilon(left->x, right->x, e) &&
		k_epsilon(left->y, right->y, e) &&
		k_epsilon(left->z, right->z, e);
}

K_INLINE kcham k_vec3_is_identity(const kVec3* pv)
{
	return (pv->x == 0.0f && pv->y == 0.0f && pv->z == 0.0f);
}

K_INLINE float k_vec3_dist_sq(const kVec3* left, const kVec3* right)
{
	kVec3 t;
	k_vec3_sub(&t, left, right);
	return k_vec3_len_sq(&t);
}

K_INLINE float k_vec3_dist(const kVec3* left, const kVec3* right)
{
	return k_sqrt(k_vec3_dist_sq(left, right));
}

K_INLINE void k_vec3_dir(kVec3* pv, const kVec3* left, const kVec3* right)
{
	k_vec3_sub(pv, left, right);
	k_vec3_norm(pv, pv);
}

K_INLINE float k_vec3_rad_sq(const kVec3* left, const kVec3* right)
{
	kVec3 t;
	k_vec3_add(&t, left, right);
	k_vec3_mag(&t, &t, 0.5f);
	k_vec3_sub(&t, &t, left);
	return k_vec3_len_sq(&t);
}

K_INLINE float k_vec3_rad(const kVec3* left, const kVec3* right)
{
	return k_sqrt(k_vec3_rad_sq(left, right));
}

K_INLINE void k_vec3_trfm(kVec4* pv, const kVec3* left, const kMat4* right)
{
	float x = left->x * right->_11 + left->y * right->_21 + left->z * right->_31 + right->_41;
	float y = left->x * right->_12 + left->y * right->_22 + left->z * right->_32 + right->_42;
	float z = left->x * right->_13 + left->y * right->_23 + left->z * right->_33 + right->_43;
	float w = left->x * right->_14 + left->y * right->_24 + left->z * right->_34 + right->_44;
	pv->x = x;
	pv->y = y;
	pv->z = z;
	pv->w = w;
}

K_INLINE void k_vec3_trfm_coord(kVec3* pv, const kVec3* left, const kMat4* right)
{
	k_vec3_set(pv,
		left->x * right->_11 + left->y * right->_21 + left->z * right->_31 + right->_41,
		left->x * right->_12 + left->y * right->_22 + left->z * right->_32 + right->_42,
		left->x * right->_13 + left->y * right->_23 + left->z * right->_33 + right->_43);
}

K_INLINE void k_vec3_trfm_norm(kVec3* pv, const kVec3* left, const kMat4* right)
{
	k_vec3_set(pv,
		left->x * right->_11 + left->y * right->_21 + left->z * right->_31,
		left->x * right->_12 + left->y * right->_22 + left->z * right->_32,
		left->x * right->_13 + left->y * right->_23 + left->z * right->_33);
}

K_INLINE void k_vec3_trfm_coord_mag(kVec3* pv, const kVec3* v, const kMat4* m, float f)
{
	float x = (v->x * m->_11 + v->y * m->_21 + v->z * m->_31 + m->_41) * f;
	float y = (v->x * m->_12 + v->y * m->_22 + v->z * m->_32 + m->_42) * f;
	float z = (v->x * m->_13 + v->y * m->_23 + v->z * m->_33 + m->_43) * f;
	pv->x += x;
	pv->y += y;
	pv->z += z;
}

K_INLINE void k_vec3_trfm_norm_mag(kVec3* pv, const kVec3* v, const kMat4* m, float f)
{
	float x = (v->x * m->_11 + v->y * m->_21 + v->z * m->_31) * f;
	float y = (v->x * m->_12 + v->y * m->_22 + v->z * m->_32) * f;
	float z = (v->x * m->_13 + v->y * m->_23 + v->z * m->_33) * f;
	pv->x += x;
	pv->y += y;
	pv->z += z;
}

K_INLINE void k_vec3_trfm_bnd(kVec3* pv, float v, const kMat4* right)
{
	pv->x = k_abs(v * right->_11 + v * right->_21 + v * right->_31);
	pv->y = k_abs(v * right->_12 + v * right->_22 + v * right->_32);
	pv->z = k_abs(v * right->_13 + v * right->_23 + v * right->_33);
}

// vector 4
KAPI void k_vec4_norm(kVec4* pv, const kVec4* v);
KAPI void k_vec4_cross(kVec4* pv, const kVec4* v1, const kVec4* v2, const kVec4* v3);
KAPI void k_vec4_interpolate(kVec4* pv, const kVec4* left, const kVec4* right, float s);
KAPI void k_vec4_lerp(kVec4* pv, const kVec4* left, const kVec4* right, float s);

K_INLINE void k_vec4_set(kVec4* pv, float x, float y, float z, float w)
{
	pv->x = x;
	pv->y = y;
	pv->z = z;
	pv->w = w;
}

K_INLINE void k_vec4_identify(kVec4* pv)
{
	pv->x = 0.0f;
	pv->y = 0.0f;
	pv->z = 0.0f;
	pv->w = 0.0f;
}

K_INLINE void k_vec4_diag(kVec4* pv, float v)
{
	pv->x = v;
	pv->y = v;
	pv->z = v;
	pv->w = v;
}

K_INLINE void k_vec4_add(kVec4* pv, const kVec4* left, const kVec4* right)
{
	pv->x = left->x + right->x;
	pv->y = left->y + right->y;
	pv->z = left->z + right->z;
	pv->w = left->w + right->w;
}

K_INLINE void k_vec4_sub(kVec4* pv, const kVec4* left, const kVec4* right)
{
	pv->x = left->x - right->x;
	pv->y = left->y - right->y;
	pv->z = left->z - right->z;
	pv->w = left->w - right->w;
}

K_INLINE void k_vec4_mag(kVec4* pv, const kVec4* left, float right)
{
	pv->x = left->x * right;
	pv->y = left->y * right;
	pv->z = left->z * right;
	pv->w = left->w * right;
}

K_INLINE void k_vec4_inc(kVec4* pv, float f)
{
	pv->x += f;
	pv->y += f;
	pv->z += f;
	pv->w += f;
}

K_INLINE void k_vec4_dec(kVec4* pv, float f)
{
	pv->x -= f;
	pv->y -= f;
	pv->z -= f;
	pv->w -= f;
}

K_INLINE float k_vec4_accum(const kVec4* pv, float s)
{
	return (pv->x + pv->y + pv->z * pv->w) * s;
}

K_INLINE void k_vec4_abs(kVec4* pv, const kVec4* v)
{
	pv->x = k_abs(v->x);
	pv->y = k_abs(v->y);
	pv->z = k_abs(v->z);
	pv->w = k_abs(v->w);
}

K_INLINE void k_vec4_invert(kVec4* pv, const kVec4* v)
{
	pv->x = -v->x;
	pv->y = -v->y;
	pv->z = -v->z;
	pv->w = -v->w;
}

K_INLINE void k_vec4_neg(kVec4* pv, const kVec4* v)
{
	pv->x = 1.0f - v->x;
	pv->y = 1.0f - v->y;
	pv->z = 1.0f - v->z;
	pv->w = 1.0f - v->w;
}

K_INLINE float k_vec4_dot(const kVec4* left, const kVec4* right)
{
	return left->x * right->x + left->y * right->y + left->z * right->z + left->w * right->w;
}

K_INLINE float k_vec4_len_sq(const kVec4* pv)
{
	return pv->x * pv->x + pv->y * pv->y + pv->z * pv->z + pv->w * pv->w;
}

K_INLINE float k_vec4_len(const kVec4* pv)
{
	return k_sqrt(k_vec4_len_sq(pv));
}

K_INLINE void k_vec4_min(kVec4* pv, const kVec4* left, const kVec4* right)
{
	pv->x = (left->x < right->x) ? left->x : right->x;
	pv->y = (left->y < right->y) ? left->y : right->y;
	pv->z = (left->z < right->z) ? left->z : right->z;
	pv->w = (left->w < right->w) ? left->w : right->w;
}

K_INLINE void k_vec4_max(kVec4* pv, const kVec4* left, const kVec4* right)
{
	pv->x = (left->x > right->x) ? left->x : right->x;
	pv->y = (left->y > right->y) ? left->y : right->y;
	pv->z = (left->z > right->z) ? left->z : right->z;
	pv->w = (left->w > right->w) ? left->w : right->w;
}

K_INLINE kcham k_vec4_eq(const kVec4* left, const kVec4* right)
{
	return
		k_eq(left->x, right->x) &&
		k_eq(left->y, right->y) &&
		k_eq(left->z, right->z) &&
		k_eq(left->w, right->w);
}

K_INLINE kcham k_vec4_epsilon(const kVec4* left, const kVec4* right, float e)
{
	return
		k_epsilon(left->x, right->x, e) &&
		k_epsilon(left->y, right->y, e) &&
		k_epsilon(left->z, right->z, e) &&
		k_epsilon(left->w, right->w, e);
}

K_INLINE kcham k_vec4_is_identity(const kVec4* pv)
{
	return (pv->x == 0.0f && pv->y == 0.0f && pv->z == 0.0f && pv->w == 0.0f);
}

K_INLINE void k_vec4_trfm(kVec4* pv, const kVec4* left, const kMat4* right)
{
	k_vec4_set(pv,
		left->x * right->_11 + left->y * right->_21 + left->z * right->_31 + left->w * right->_41,
		left->x * right->_12 + left->y * right->_22 + left->z * right->_32 + left->w * right->_42,
		left->x * right->_13 + left->y * right->_23 + left->z * right->_33 + left->w * right->_43,
		left->x * right->_14 + left->y * right->_24 + left->z * right->_34 + left->w * right->_44);
}

// quaternion
KAPI void k_quat_mul(kQuat* pq, const kQuat* left, const kQuat* right);
KAPI void k_quat_inv(kQuat* pq, const kQuat* q);
KAPI void k_quat_cross(kQuat* pq, const kQuat* q1, const kQuat* q2, const kQuat* q3);
KAPI void k_quat_norm(kQuat* pq, const kQuat* q);
KAPI void k_quat_exp(kQuat* pq, const kQuat* q);
KAPI void k_quat_ln(kQuat* pq, const kQuat* q);
KAPI void k_quat_interpolate(kQuat* pq, const kQuat* left, const kQuat* right, float s);
KAPI void k_quat_lerp(kQuat* pq, const kQuat* left, const kQuat* right, float s);
KAPI void k_quat_slerp(kQuat* pq, const kQuat* left, const kQuat* right, float t);
KAPI void k_quat_squad(kQuat* pq, const kQuat* q1, const kQuat* q2, const kQuat* q3, const kQuat* q4, float t);
KAPI void k_quat_rot_x(kQuat* pq, float x);
KAPI void k_quat_rot_y(kQuat* pq, float y);
KAPI void k_quat_rot_z(kQuat* pq, float z);
KAPI void k_quat_rot_mat(kQuat* pq, const kMat4* m);
KAPI void k_quat_rot_vec(kQuat* pq, const kVec3* v);
KAPI void k_quat_rot_axis_vec(kQuat* pq, const kVec3* v, float angle);
KAPI void k_quat_bary_centric(kQuat* pq, const kQuat* q1, const kQuat* q2, const kQuat* q3, float f, float g);

K_INLINE void k_quat_set(kQuat* pq, float x, float y, float z, float w)
{
	pq->x = x;
	pq->y = y;
	pq->z = z;
	pq->w = w;
}

K_INLINE void k_quat_zero(kQuat* pq)
{
	pq->x = 0.0f;
	pq->y = 0.0f;
	pq->z = 0.0f;
	pq->w = 0.0f;
}

K_INLINE void k_quat_identify(kQuat* pq)
{
	pq->x = 0.0f;
	pq->y = 0.0f;
	pq->z = 0.0f;
	pq->w = 1.0f;
}

K_INLINE void k_quat_add(kQuat* pq, const kQuat* left, const kQuat* right)
{
	pq->x = left->x + right->x;
	pq->y = left->y + right->y;
	pq->z = left->z + right->z;
	pq->w = left->w + right->w;
}

K_INLINE void k_quat_sub(kQuat* pq, const kQuat* left, const kQuat* right)
{
	pq->x = left->x - right->x;
	pq->y = left->y - right->y;
	pq->z = left->z - right->z;
	pq->w = left->w - right->w;
}

K_INLINE void k_quat_mag(kQuat* pq, const kQuat* left, float right)
{
	pq->x = left->x * right;
	pq->y = left->y * right;
	pq->z = left->z * right;
	pq->w = left->w * right;
}

K_INLINE void k_quat_inc(kQuat* pq, float f)
{
	pq->x += f;
	pq->y += f;
	pq->z += f;
	pq->w += f;
}

K_INLINE void k_quat_dec(kQuat* pq, float f)
{
	pq->x -= f;
	pq->y -= f;
	pq->z -= f;
	pq->w -= f;
}

K_INLINE void k_quat_abs(kQuat* pq, const kQuat* v)
{
	pq->x = k_abs(v->x);
	pq->y = k_abs(v->y);
	pq->z = k_abs(v->z);
	pq->w = k_abs(v->w);
}

K_INLINE void k_quat_invert(kQuat* pq, const kQuat* v)
{
	pq->x = -v->x;
	pq->y = -v->y;
	pq->z = -v->z;
	pq->w = -v->w;
}

K_INLINE void k_quat_neg(kQuat* pq, const kQuat* v)
{
	pq->x = 1.0f - v->x;
	pq->y = 1.0f - v->y;
	pq->z = 1.0f - v->z;
	pq->w = 1.0f - v->w;
}

K_INLINE void k_quat_conjugate(kQuat* pq, const kQuat* q)
{
	pq->x = -q->x;
	pq->y = -q->y;
	pq->z = -q->z;
	pq->w = q->w;
}

K_INLINE float k_quat_dot(const kQuat* left, const kQuat* right)
{
	return left->x * right->x + left->y * right->y + left->z * right->z + left->w * right->w;
}

K_INLINE float k_quat_len_sq(const kQuat* pq)
{
	return pq->x * pq->x + pq->y * pq->y + pq->z * pq->z + pq->w * pq->w;
}

K_INLINE float k_quat_len(const kQuat* pq)
{
	return k_sqrt(k_quat_len_sq(pq));
}

K_INLINE void k_quat_min(kQuat* pq, const kQuat* left, const kQuat* right)
{
	pq->x = (left->x < right->x) ? left->x : right->x;
	pq->y = (left->y < right->y) ? left->y : right->y;
	pq->z = (left->z < right->z) ? left->z : right->z;
	pq->w = (left->w < right->w) ? left->w : right->w;
}

K_INLINE void k_quat_max(kQuat* pq, const kQuat* left, const kQuat* right)
{
	pq->x = (left->x > right->x) ? left->x : right->x;
	pq->y = (left->y > right->y) ? left->y : right->y;
	pq->z = (left->z > right->z) ? left->z : right->z;
	pq->w = (left->w > right->w) ? left->w : right->w;
}

K_INLINE kcham k_quat_eq(const kQuat* left, const kQuat* right)
{
	return
		k_eq(left->x, right->x) &&
		k_eq(left->y, right->y) &&
		k_eq(left->z, right->z) &&
		k_eq(left->w, right->w);
}

K_INLINE kcham k_quat_epsilon(const kQuat* left, const kQuat* right, float e)
{
	return
		k_epsilon(left->x, right->x, e) &&
		k_epsilon(left->y, right->y, e) &&
		k_epsilon(left->z, right->z, e) &&
		k_epsilon(left->w, right->w, e);
}

K_INLINE kcham k_quat_is_identity(const kQuat* pq)
{
	return (pq->x == 0.0f && pq->y == 0.0f && pq->z == 0.0f && pq->w == 1.0f);
}

// matrix 4
KAPI void k_mat4_mul(kMat4* pm, const kMat4* left, const kMat4* right);
KAPI void k_mat4_tran(kMat4* pm, const kMat4* m);
KAPI void k_mat4_inv(kMat4* pm, float* retdet, const kMat4* m);
KAPI float k_mat4_det(const kMat4* m);
KAPI void k_mat4_mul_tran(kMat4* pm, const kMat4* left, const kMat4* right);
KAPI void k_mat4_array_tran(kMat4* pm, kint cnt, kMat4* m);
KAPI void k_mat4_rep_lerp_len(kMat4* pm, const kVec3* left, const kVec3* right, float s);
KAPI void k_mat4_rep_rot_quat(kMat4* pm, const kQuat* q);
KAPI void k_mat4_rot_vec(kMat4* pm, const kVec3* v);
KAPI void k_mat4_rot_quat(kMat4* pm, const kQuat* q);
KAPI void k_mat4_rot_x(kMat4* pm, float f);
KAPI void k_mat4_rot_y(kMat4* pm, float f);
KAPI void k_mat4_rot_z(kMat4* pm, float f);
KAPI void k_mat4_lookat_lh(kMat4* pm, const kVec3* Eye, const kVec3* At, const kVec3* Up);
KAPI void k_mat4_lookat_rh(kMat4* pm, const kVec3* Eye, const kVec3* At, const kVec3* Up);
KAPI void k_mat4_perspective_lh(kMat4* pm, float fov, float aspect, float zn, float zf);
KAPI void k_mat4_perspective_rh(kMat4* pm, float fov, float aspect, float zn, float zf);
KAPI void k_mat4_ortho_lh(kMat4* pm, float width, float height, float zn, float zf);
KAPI void k_mat4_ortho_rh(kMat4* pm, float width, float height, float zn, float zf);
KAPI void k_mat4_ortho_offcenter_lh(kMat4* pm, float l, float r, float b, float t, float zn, float zf);
KAPI void k_mat4_ortho_offcenter_rh(kMat4* pm, float l, float r, float b, float t, float zn, float zf);
KAPI void k_mat4_viewport(kMat4* pm, float x, float y, float width, float height);
KAPI void k_mat4_shadow(kMat4* pm, const kVec4* lgt, const kPln* pl);
KAPI void k_mat4_affine(kMat4* pm, const kVec3* scl, const kVec3* rotcenter, const kQuat* rot, const kVec3* loc);
KAPI void k_mat4_interpolate(kMat4* pm, const kMat4* left, const kMat4* right, float f);
KAPI void k_mat4_trfm(kMat4* m, const kVec3* loc, const kQuat* rot, const kVec3* scl);
KAPI void k_mat4_trfm_vec(kMat4* m, const kVec3* loc, const kVec3* rot, const kVec3* scl);

K_INLINE void k_mat4_zero(kMat4* pm)
{
	pm->_11 = pm->_12 = pm->_13 = pm->_14 = 0.0f;
	pm->_21 = pm->_22 = pm->_23 = pm->_24 = 0.0f;
	pm->_31 = pm->_32 = pm->_33 = pm->_34 = 0.0f;
	pm->_41 = pm->_42 = pm->_43 = pm->_44 = 0.0f;
}

K_INLINE void k_mat4_identify(kMat4* pm)
{
	pm->_12 = pm->_13 = pm->_14 = 0.0f;
	pm->_21 = pm->_23 = pm->_24 = 0.0f;
	pm->_31 = pm->_32 = pm->_34 = 0.0f;
	pm->_41 = pm->_42 = pm->_43 = 0.0f;
	pm->_11 = pm->_22 = pm->_33 = pm->_44 = 1.0f;
}

K_INLINE void k_mat4_diag(kMat4* pm, float v)
{
	pm->_12 = pm->_13 = pm->_14 = 0.0f;
	pm->_21 = pm->_23 = pm->_24 = 0.0f;
	pm->_31 = pm->_32 = pm->_34 = 0.0f;
	pm->_41 = pm->_42 = pm->_43 = 0.0f;
	pm->_11 = pm->_22 = pm->_33 = pm->_44 = v;
}

K_INLINE void k_mat4_add(kMat4* pm, const kMat4* left, const kMat4* right)
{
	pm->_11 = left->_11 + right->_11;
	pm->_12 = left->_12 + right->_12;
	pm->_13 = left->_13 + right->_13;
	pm->_14 = left->_14 + right->_14;
	pm->_21 = left->_21 + right->_21;
	pm->_22 = left->_22 + right->_22;
	pm->_23 = left->_23 + right->_23;
	pm->_24 = left->_24 + right->_24;
	pm->_31 = left->_31 + right->_31;
	pm->_32 = left->_32 + right->_32;
	pm->_33 = left->_33 + right->_33;
	pm->_34 = left->_34 + right->_34;
	pm->_41 = left->_41 + right->_41;
	pm->_42 = left->_42 + right->_42;
	pm->_43 = left->_43 + right->_43;
	pm->_44 = left->_44 + right->_44;
}

K_INLINE void k_mat4_sub(kMat4* pm, const kMat4* left, const kMat4* right)
{
	pm->_11 = left->_11 - right->_11;
	pm->_12 = left->_12 - right->_12;
	pm->_13 = left->_13 - right->_13;
	pm->_14 = left->_14 - right->_14;
	pm->_21 = left->_21 - right->_21;
	pm->_22 = left->_22 - right->_22;
	pm->_23 = left->_23 - right->_23;
	pm->_24 = left->_24 - right->_24;
	pm->_31 = left->_31 - right->_31;
	pm->_32 = left->_32 - right->_32;
	pm->_33 = left->_33 - right->_33;
	pm->_34 = left->_34 - right->_34;
	pm->_41 = left->_41 - right->_41;
	pm->_42 = left->_42 - right->_42;
	pm->_43 = left->_43 - right->_43;
	pm->_44 = left->_44 - right->_44;
}

K_INLINE void k_mat4_mag(kMat4* pm, const kMat4* left, float right)
{
	pm->_11 = left->_11 * right;
	pm->_12 = left->_12 * right;
	pm->_13 = left->_13 * right;
	pm->_14 = left->_14 * right;
	pm->_21 = left->_21 * right;
	pm->_22 = left->_22 * right;
	pm->_23 = left->_23 * right;
	pm->_24 = left->_24 * right;
	pm->_31 = left->_31 * right;
	pm->_32 = left->_32 * right;
	pm->_33 = left->_33 * right;
	pm->_34 = left->_34 * right;
	pm->_41 = left->_41 * right;
	pm->_42 = left->_42 * right;
	pm->_43 = left->_43 * right;
	pm->_44 = left->_44 * right;
}

K_INLINE void k_mat4_loc(kMat4* pm, float x, float y, float z)
{
	pm->_12 = pm->_13 = pm->_14 = 0.0f;
	pm->_21 = pm->_23 = pm->_24 = 0.0f;
	pm->_31 = pm->_32 = pm->_34 = 0.0f;
	pm->_11 = pm->_22 = pm->_33 = pm->_44 = 1.0f;
	pm->_41 = x;
	pm->_42 = y;
	pm->_43 = z;
}

K_INLINE void k_mat4_scl(kMat4* pm, float x, float y, float z)
{
	pm->_12 = pm->_13 = pm->_14 = 0.0f;
	pm->_21 = pm->_23 = pm->_24 = 0.0f;
	pm->_31 = pm->_32 = pm->_34 = 0.0f;
	pm->_41 = pm->_42 = pm->_43 = 0.0f;
	pm->_11 = x;
	pm->_22 = y;
	pm->_33 = z;
	pm->_44 = 1.0f;
}

K_INLINE void k_mat4_rep_loc(kMat4* pm, float x, float y, float z)
{
	pm->_41 = x;
	pm->_42 = y;
	pm->_43 = z;
}

K_INLINE void k_mat4_rep_addloc(kMat4* pm, float x, float y, float z)
{
	pm->_41 += x;
	pm->_42 += y;
	pm->_43 += z;
}

K_INLINE void k_mat4_rep_scl(kMat4* pm, float x, float y, float z)
{
	pm->_11 = x;
	pm->_22 = y;
	pm->_33 = z;
}

K_INLINE kcham k_mat4_eq(const kMat4* left, const kMat4* right)
{
	return memcmp(left, right, sizeof(kMat4)) == 0;
}

K_INLINE kcham k_mat4_is_identity(const kMat4* pm)
{
	return
		pm->_11 == 1.0f && pm->_12 == 0.0f && pm->_13 == 0.0f && pm->_14 == 0.0f &&
		pm->_21 == 0.0f && pm->_22 == 1.0f && pm->_23 == 0.0f && pm->_24 == 0.0f &&
		pm->_31 == 0.0f && pm->_32 == 0.0f && pm->_33 == 1.0f && pm->_34 == 0.0f &&
		pm->_41 == 0.0f && pm->_42 == 0.0f && pm->_43 == 0.0f && pm->_44 == 1.0f;
}

// quad
K_INLINE void k_qd_set(kQd* pq, float left, float top, float right, float bottom)
{
	pq->left = left;
	pq->top = top;
	pq->right = right;
	pq->bottom = bottom;
}

K_INLINE void k_qd_zero(kQd* pq)
{
	pq->left = 0.0f;
	pq->top = 0.0f;
	pq->right = 0.0f;
	pq->bottom = 0.0f;
}

K_INLINE void k_qd_mag(kQd* p, const kQd* rt, float w, float h)
{
	p->left = rt->left - w;
	p->top = rt->top - h;
	p->right = rt->right + w;
	p->bottom = rt->bottom + h;
}

K_INLINE void k_qd_inflate(kQd* p, const kQd* rt, float l, float t, float r, float b)
{
	p->left = rt->left - l;
	p->top = rt->top - t;
	p->right = rt->right + r;
	p->bottom = rt->bottom + b;
}

K_INLINE void k_qd_deflate(kQd* p, const kQd* rt, float l, float t, float r, float b)
{
	p->left = rt->left + l;
	p->top = rt->top + t;
	p->right = rt->right - r;
	p->bottom = rt->bottom - b;
}

K_INLINE void k_qd_offset(kQd* p, const kQd* rt, float l, float t, float r, float b)
{
	p->left = rt->left + l;
	p->top = rt->top + t;
	p->right = rt->right + r;
	p->bottom = rt->bottom + b;
}

K_INLINE float k_qd_width(const kQd* pq)
{
	return pq->right - pq->left;
}

K_INLINE float k_qd_height(const kQd* pq)
{
	return pq->bottom - pq->top;
}

K_INLINE kcham k_qd_have(const kQd* pq, float x, float y)
{
	return (x >= pq->left && x <= pq->right && y >= pq->top && y <= pq->bottom);
}

K_INLINE kcham k_qd_intersect(kQd* p, const kQd* q1, const kQd* q2)
{
	int i = q2->left < q1->right && q2->right > q1->left && q2->top < q1->bottom && q2->bottom > q1->top;

	if (!i)
		k_qd_set(p, 0.0f, 0.0f, 0.0f, 0.0f);
	else
	{
		k_qd_set(p,
			K_MAX(q1->left, q2->left), K_MAX(q1->top, q2->top),
			K_MIN(q1->right, q2->right), K_MIN(q1->bottom, q2->bottom));
	}

	return i;
}

// point
K_INLINE void k_pt_set(kPt* pt, kint x, kint y)
{
	pt->x = x;
	pt->y = y;
}

K_INLINE void k_pt_set_mm(kPt* pt, kint min, kint max)
{
	pt->min = min;
	pt->max = max;
}

K_INLINE void k_pt_set_size(kPt* pt, const kRt* rt)
{
	pt->x = rt->right - rt->left;
	pt->y = rt->bottom - rt->top;
}

K_INLINE float k_pt_aspect(const kPt* pt)
{
	return (float)pt->x / (float)pt->y;
}

K_INLINE kcham k_pt_between(const kPt* pt, kint v)
{
	return v > pt->min && v < pt->max;
}

// rect
K_INLINE void k_rt_set(kRt* prt, kint left, kint top, kint right, kint bottom)
{
	prt->left = left;
	prt->top = top;
	prt->right = right;
	prt->bottom = bottom;
}

K_INLINE void k_rt_set_size(kRt* p, kint x, kint y, kint w, kint h)
{
	p->left = x;
	p->top = y;
	p->right = x + w;
	p->bottom = y + h;
}

K_INLINE void k_rt_zero(kRt* prt)
{
	prt->left = 0;
	prt->top = 0;
	prt->right = 0;
	prt->bottom = 0;
}

K_INLINE void k_rt_mag(kRt* p, const kRt* rt, kint w, kint h)
{
	p->left = rt->left - w;
	p->top = rt->top - h;
	p->right = rt->right + w;
	p->bottom = rt->bottom + h;
}

K_INLINE void k_rt_inflate(kRt* p, const kRt* rt, kint l, kint t, kint r, kint b)
{
	p->left = rt->left - l;
	p->top = rt->top - t;
	p->right = rt->right + r;
	p->bottom = rt->bottom + b;
}

K_INLINE void k_rt_deflate(kRt* p, const kRt* rt, kint l, kint t, kint r, kint b)
{
	p->left = rt->left + l;
	p->top = rt->top + t;
	p->right = rt->right - r;
	p->bottom = rt->bottom - b;
}

K_INLINE void k_rt_offset(kRt* p, const kRt* rt, kint l, kint t, kint r, kint b)
{
	p->left = rt->left + l;
	p->top = rt->top + t;
	p->right = rt->right + r;
	p->bottom = rt->bottom + b;
}

K_INLINE kint k_rt_width(const kRt* prt)
{
	return prt->right - prt->left;
}

K_INLINE kint k_rt_height(const kRt* prt)
{
	return prt->bottom - prt->top;
}

K_INLINE kcham k_rt_have(const kRt* prt, kint x, kint y)
{
	return (x >= prt->left && x <= prt->right && y >= prt->top && y <= prt->bottom);
}

K_INLINE kcham k_rt_eq(const kRt* r1, const kRt* r2)
{
	return r1->left == r2->left && r1->right == r2->right && r1->top == r2->top && r1->bottom == r2->bottom;
}

K_INLINE kcham k_rt_intersect(kRt* p, const kRt* r1, const kRt* r2)
{
	int i = (
		r2->left < r1->right &&
		r2->right > r1->left &&
		r2->top < r1->bottom &&
		r2->bottom > r1->top);

	if (!i)
		k_rt_set(p, 0, 0, 0, 0);
	else
	{
		k_rt_set(p,
			K_MAX(r1->left, r2->left), K_MAX(r1->top, r2->top),
			K_MIN(r1->right, r2->right), K_MIN(r1->bottom, r2->bottom));
	}

	return i;
}

// color
K_INLINE void k_cr_set(kCr* pc, float r, float g, float b, float a)
{
	pc->r = r;
	pc->g = g;
	pc->b = b;
	pc->a = a;
}

K_INLINE void k_cr_set_uint(kCr* pc, kuint value)
{
	float f = 1.0f / 255.0f;
	pc->b = (float)(value & 255) * f;
	value >>= 8;
	pc->g = (float)(value & 255) * f;
	value >>= 8;
	pc->r = (float)(value & 255) * f;
	value >>= 8;
	pc->a = (float)(value & 255) * f;
	value >>= 8;
}

K_INLINE void k_cr_set_cu(kCr* pc, const kCu* cu)
{
	float f = 1.0f / 255.0f;
	pc->a = (float)cu->a * f;
	pc->r = (float)cu->r * f;
	pc->g = (float)cu->g * f;
	pc->b = (float)cu->b * f;
}

K_INLINE void k_cr_add(kCr* pc, const kCr* left, const kCr* right)
{
	pc->r = left->r + right->r;
	pc->g = left->g + right->b;
	pc->b = left->b + right->b;
	pc->a = left->a + right->a;
}

K_INLINE void k_cr_sub(kCr* pc, const kCr* left, const kCr* right)
{
	pc->r = left->r - right->r;
	pc->g = left->g - right->b;
	pc->b = left->b - right->b;
	pc->a = left->a - right->a;
}

K_INLINE void k_cr_mag(kCr* pc, const kCr* left, float scale)
{
	pc->r = left->r * scale;
	pc->g = left->g * scale;
	pc->b = left->b * scale;
	pc->a = left->a * scale;
}

K_INLINE void k_cr_neg(kCr* pc, const kCr* c)
{
	pc->r = 1.0f - c->r;
	pc->g = 1.0f - c->g;
	pc->b = 1.0f - c->b;
	pc->a = c->a;
}

K_INLINE void k_cr_interpolate(kCr* pc, const kCr* left, const kCr* right, float s)
{
	// left=tocolor, right=fromcolor
	float f = 1.0f - s;
	pc->r = right->r * f + left->r * s;
	pc->g = right->g * f + left->g * s;
	pc->b = right->b * f + left->b * s;
	pc->a = right->a * f + left->a * s;
}

K_INLINE void k_cr_lerp(kCr* pc, const kCr* left, const kCr* right, float s)
{
	pc->r = left->r + s * (right->r - left->r);
	pc->g = left->g + s * (right->g - left->g);
	pc->b = left->b + s * (right->b - left->b);
	pc->a = left->a + s * (right->a - left->a);
}

K_INLINE void k_cr_mod(kCr* pc, const kCr* left, const kCr* right)
{
	pc->r = left->r * right->r;
	pc->g = left->g * right->g;
	pc->b = left->b * right->b;
	pc->a = left->a * right->a;
}

K_INLINE void k_cr_min(kCr* pc, const kCr* left, const kCr* right)
{
	pc->r = (left->r < right->r) ? left->r : right->r;
	pc->g = (left->g < right->g) ? left->g : right->g;
	pc->b = (left->b < right->b) ? left->b : right->b;
	pc->a = (left->a < right->a) ? left->a : right->a;
}

K_INLINE void k_cr_max(kCr* pc, const kCr* left, const kCr* right)
{
	pc->r = (left->r > right->r) ? left->r : right->r;
	pc->g = (left->g > right->g) ? left->g : right->g;
	pc->b = (left->b > right->b) ? left->b : right->b;
	pc->a = (left->a > right->a) ? left->a : right->a;
}

K_INLINE float* k_cr_float(kCr* c)
{
	return &c->r;
}

K_INLINE kuint k_cr_uint(const kCr* pc)
{
	kuint R = (pc->r >= 1.0f) ? 0xff : (pc->r <= 0.0f) ? 0x00 : (kuint)(pc->r * 255.0f + 0.5f);
	kuint G = (pc->g >= 1.0f) ? 0xff : (pc->g <= 0.0f) ? 0x00 : (kuint)(pc->g * 255.0f + 0.5f);
	kuint B = (pc->b >= 1.0f) ? 0xff : (pc->b <= 0.0f) ? 0x00 : (kuint)(pc->b * 255.0f + 0.5f);
	kuint A = (pc->a >= 1.0f) ? 0xff : (pc->a <= 0.0f) ? 0x00 : (kuint)(pc->a * 255.0f + 0.5f);
	return (A << 24) | (R << 16) | (G << 8) | B;
}

K_INLINE kuint k_cr_uint_simple(const kCr* pc)
{
	kbyte R = (kbyte)(pc->r * 255.0f + 0.5f);
	kbyte G = (kbyte)(pc->g * 255.0f + 0.5f);
	kbyte B = (kbyte)(pc->b * 255.0f + 0.5f);
	kbyte A = (kbyte)(pc->a * 255.0f + 0.5f);
	return ((kuint)A << 24) | ((kuint)R << 16) | ((kuint)G << 8) | (kuint)B;
}

K_INLINE kcham k_cr_eq(const kCr* left, const kCr* right)
{
	return
		k_eq(left->r, right->r) &&
		k_eq(left->g, right->g) &&
		k_eq(left->b, right->b) &&
		k_eq(left->a, right->a);
}

K_INLINE kcham k_cr_epsilon(const kCr* left, const kCr* right, float e)
{
	return
		k_epsilon(left->r, right->r, e) &&
		k_epsilon(left->g, right->g, e) &&
		k_epsilon(left->b, right->b, e) &&
		k_epsilon(left->a, right->a, e);
}

K_INLINE void k_cr_contrast(kCr* pc, const kCr* c, float s)
{
	pc->r = 0.5f + s * (c->r - 0.5f);
	pc->g = 0.5f + s * (c->g - 0.5f);
	pc->b = 0.5f + s * (c->b - 0.5f);
	pc->a = c->a;
}

K_INLINE void k_cr_saturation(kCr* pc, const kCr* c, float s)
{
	float g = c->r * 0.2125f + c->g * 0.7154f + c->b * 0.0721f;
	pc->r = g + s * (c->r - g);
	pc->g = g + s * (c->g - g);
	pc->b = g + s * (c->b - g);
	pc->a = c->a;
}

// uni color
K_INLINE void k_cu_set(kCu* pc, kbyte r, kbyte g, kbyte b, kbyte a)
{
	pc->r = r;
	pc->g = g;
	pc->b = b;
	pc->a = a;
}

K_INLINE void k_cu_set_float(kCu* pc, float r, float g, float b, float a)
{
	pc->r = (kbyte)k_rint(r * 255.0f);
	pc->g = (kbyte)k_rint(g * 255.0f);
	pc->b = (kbyte)k_rint(b * 255.0f);
	pc->a = (kbyte)k_rint(a * 255.0f);
}

K_INLINE void k_cu_set_uint(kCu* pc, kuint value)
{
	((kUcu*)pc)->v = value;
}

K_INLINE void k_cu_set_cr(kCu* pc, const kCr* cr)
{
	pc->r = (kbyte)k_rint(cr->r * 255.0f);
	pc->g = (kbyte)k_rint(cr->g * 255.0f);
	pc->b = (kbyte)k_rint(cr->b * 255.0f);
	pc->a = (kbyte)k_rint(cr->a * 255.0f);
}

K_INLINE void k_cu_add(kCu* pc, const kCu* left, const kCu* right)
{
	((kUcu*)pc)->v = ((kUcu*)left)->v + ((kUcu*)right)->v;
}

K_INLINE void k_cu_sub(kCu* pc, const kCu* left, const kCu* right)
{
	((kUcu*)pc)->v = ((kUcu*)left)->v - ((kUcu*)right)->v;
}

K_INLINE void k_cu_mag(kCu* pc, const kCu* left, float scale)
{
	pc->r = (kbyte)k_rint(left->r * scale);
	pc->g = (kbyte)k_rint(left->g * scale);
	pc->b = (kbyte)k_rint(left->b * scale);
	pc->a = (kbyte)k_rint(left->a * scale);
}

K_INLINE void k_cu_neg(kCu* pc, const kCu* c)
{
	pc->r = 255 - c->r;
	pc->g = 255 - c->g;
	pc->b = 255 - c->b;
	pc->a = c->a;
}

K_INLINE void k_cu_interpolate(kCu* pc, const kCu* left, const kCu* right, float s)
{
	// left=tocolor, right=fromcolor
	float f = 1.0f - s;
	pc->r = (kbyte)k_rint(right->r * f + left->r * s);
	pc->g = (kbyte)k_rint(right->g * f + left->g * s);
	pc->b = (kbyte)k_rint(right->b * f + left->b * s);
	pc->a = (kbyte)k_rint(right->a * f + left->a * s);
}

K_INLINE void k_cu_lerp(kCu* pc, const kCu* left, const kCu* right, float s)
{
	pc->r = (kbyte)k_rint(left->r + s * (right->r - left->r));
	pc->g = (kbyte)k_rint(left->g + s * (right->g - left->g));
	pc->b = (kbyte)k_rint(left->b + s * (right->b - left->b));
	pc->a = (kbyte)k_rint(left->a + s * (right->a - left->a));
}

K_INLINE void k_cu_mod(kCu* pc, const kCu* left, const kCu* right)
{
	pc->r = left->r * right->r;
	pc->g = left->g * right->g;
	pc->b = left->b * right->b;
	pc->a = left->a * right->a;
}

K_INLINE void k_cu_min(kCu* pc, const kCu* left, const kCu* right)
{
	pc->r = (left->r < right->r) ? left->r : right->r;
	pc->g = (left->g < right->g) ? left->g : right->g;
	pc->b = (left->b < right->b) ? left->b : right->b;
	pc->a = (left->a < right->a) ? left->a : right->a;
}

K_INLINE void k_cu_max(kCu* pc, const kCu* left, const kCu* right)
{
	pc->r = (left->r > right->r) ? left->r : right->r;
	pc->g = (left->g > right->g) ? left->g : right->g;
	pc->b = (left->b > right->b) ? left->b : right->b;
	pc->a = (left->a > right->a) ? left->a : right->a;
}

K_INLINE kuint k_cu_uint(const kCu* pc)
{
	return ((kUcu*)pc)->v;
}

K_INLINE kcham k_cu_eq(const kCu* left, const kCu* right)
{
#if 0
	return
		left->r == right->r &&
		left->g == right->g &&
		left->b == right->b &&
		left->a == right->a;
#else
	return ((kUcu*)left)->v == ((kUcu*)right)->v;
#endif
}

K_INLINE void k_cu_contrast(kCu* pc, const kCu* c, float s)
{
	pc->r = (kbyte)k_rint(s * (c->r - 0.5f));
	pc->g = (kbyte)k_rint(s * (c->g - 0.5f));
	pc->b = (kbyte)k_rint(s * (c->b - 0.5f));
	pc->a = c->a;
}

K_INLINE void k_cu_saturation(kCu* pc, const kCu* c, float s)
{
	float g = c->r * 0.2125f + c->g * 0.7154f + c->b * 0.0721f;
	pc->r = (kbyte)k_rint(g + s * (c->r - g));
	pc->g = (kbyte)k_rint(g + s * (c->g - g));
	pc->b = (kbyte)k_rint(g + s * (c->b - g));
	pc->a = c->a;
}

// plane
KAPI void k_pln_norm(kPln* pp, const kPln* p);
KAPI void k_pln_revnorm(kPln* pp, const kPln* p);
KAPI void k_pln_trfm(kPln* pp, const kPln* left, const kMat4* right);
KAPI void k_pln_from_points(kPln* pp, const kVec3* v1, const kVec3* v2, const kVec3* v3);
KAPI float k_pln_intersect_line(const kPln* p, const kVec3* v1, const kVec3* v2);
KAPI kcham k_pln_intersect_plane(const kPln* p, const kPln* o1, const kPln* o2);
KAPI kcham k_pln_test_intersect_pln(const kPln* p, kVec3* loc, kVec3* dir, const kPln* o);

K_INLINE void k_pln_identify(kPln* pp)
{
	pp->a = pp->b = pp->c = 0.0f;
	pp->d = 1.0f;
}

K_INLINE void k_pln_set(kPln* pp, float a, float b, float c, float d)
{
	pp->a = a;
	pp->b = b;
	pp->c = c;
	pp->d = d;
}

K_INLINE float k_pln_dot_coord(const kPln* pp, const kVec3* v)
{
	return pp->a * v->x + pp->b * v->y + pp->c * v->z + pp->d;
}

K_INLINE void k_pln_from_point_norm(kPln* pp, const kVec3* pv, const kVec3* pn)
{
	pp->a = pn->x;
	pp->b = pn->y;
	pp->c = pn->z;
	pp->d = -k_vec3_dot(pv, pn);
}

K_INLINE kint k_pln_relation_point(const kPln* p, const kVec3* v)
{
	float f = k_vec3_dot((const kVec3*)p, v) + p->d;

	if (f < -KM_EPSILON)
		return -1;  // back

	if (f > KM_EPSILON)
		return 1;   // front

	return 0;       // on
}

K_INLINE float k_pln_dist(const kPln* p, const kVec3* v)
{
	return k_vec3_dot(v, (const kVec3*)p) + p->d;
}

// line 3
KAPI kcham k_ln3_intersect_sphere(const kLn3* p, const kVec3* org, float rad, float* dist);

K_INLINE void k_ln3_set(kLn3* p, float bx, float by, float bz, float ex, float ey, float ez)
{
	k_vec3_set(&p->begin, bx, by, bz);
	k_vec3_set(&p->end, ex, ey, ez);
}

K_INLINE void k_ln3_set_vec(kLn3* p, const kVec3* begin, const kVec3* end)
{
	p->begin = *begin;
	p->end = *end;
}

K_INLINE void k_ln3_add(kLn3* p, const kLn3* l, const kVec3* v)
{
	k_vec3_add(&p->begin, &l->begin, v);
	k_vec3_add(&p->end, &l->end, v);
}

K_INLINE void k_ln3_sub(kLn3* p, const kLn3* l, const kVec3* v)
{
	k_vec3_sub(&p->begin, &l->begin, v);
	k_vec3_sub(&p->end, &l->end, v);
}

K_INLINE float k_ln3_len_sq(const kLn3* p)
{
	return k_vec3_dist_sq(&p->begin, &p->end);
}

K_INLINE float k_ln3_len(const kLn3* p)
{
	return k_vec3_dist(&p->begin, &p->end);
}

K_INLINE void k_ln3_center(const kLn3* p, kVec3* v)
{
	k_vec3_add(v, &p->begin, &p->end);
	k_vec3_mag(v, v, 0.5f);
}

K_INLINE void k_ln3_vec(const kLn3* p, kVec3* v)
{
	k_vec3_sub(v, &p->end, &p->begin);
}

K_INLINE kcham k_ln3_have(const kLn3* p, const kVec3* v)
{
	return k_vec3_between(v, &p->begin, &p->end);
}

// half type
K_INLINE khalf k_ftohf(const float v)
{
	kuint r, s;
	union
	{
		kuint	u;
		float	f;
	} i;

	KSAFE_BARRIER;

	i.f = (float)v;
	s = (i.u & 0x80000000U) >> 16U;
	i.u = i.u & 0x7FFFFFFFU;

	if (i.u > 0x47FFEFFFU)
		r = 0x7FFFU;
	else
	{
		if (i.u >= 0x38800000U)
			i.u += 0xC8000000U;
		else
		{
			kuint t = 113U - (i.u >> 23U);
			i.u = (0x800000U | (i.u & 0x7FFFFFU)) >> t;
		}

		r = ((i.u + 0x0FFFU + ((i.u >> 13U) & 1U)) >> 13U) & 0x7FFFU;
	}

	return (khalf)(r | s);
}

K_INLINE float k_hftof(const khalf v)
{
	kuint m, e;
	union
	{
		kuint	u;
		float	f;
	} r;

	KSAFE_BARRIER;

	m = (kuint)(v & 0x03FF);

	if ((v & 0x7C00) != 0)
		e = (kuint)((v >> 10) & 0x1F);
	else if (m != 0)
	{
		e = 1;

		do
		{
			e--;
			m <<= 1;
		} while ((m & 0x0400) == 0);

		m &= 0x03FF;
	}
	else
		e = (kuint)-112;

	r.u = ((v & 0x8000) << 16) | ((e + 112) << 23) | (m << 13);
	return r.f;
}

// vec half
K_INLINE void k_vech2_set(kVecH2* p, float x, float y)
{
	p->x = k_ftohf(x);
	p->y = k_ftohf(y);
}

K_INLINE void k_vech3_set(kVecH3* p, float x, float y, float z)
{
	p->x = k_ftohf(x);
	p->y = k_ftohf(y);
	p->z = k_ftohf(z);
}

K_INLINE void k_vech4_set(kVecH4* p, float x, float y, float z, float w)
{
	p->x = k_ftohf(x);
	p->y = k_ftohf(y);
	p->z = k_ftohf(z);
	p->w = k_ftohf(w);
}

K_EXTERN_C_END





















#ifdef __cplusplus
//////////////////////////////////////////////////////////////////////////
// C++ math class






















//////////////////////////////////////////////////////////////////////////
// type declaration
namespace tpl
{
	// fore-decl
	struct Vec2;
	struct Vec3;
	struct Vec4;
	struct Quat;
	struct Mat4;
	struct Point;
	struct Rect;
	struct Quad;
	struct Color;
	struct Plane;
	struct Line3;
	struct TrFm;
	struct VecH2;
	struct VecH3;
	struct VecH4;


	// vector2
	struct Vec2 : public kVec2
	{
		Vec2() {}
		Vec2(float x, float y);
		Vec2(const kVec2& right);

		Vec2& operator+=(const Vec2& right);
		Vec2& operator-=(const Vec2& right);
		Vec2& operator+=(float right);
		Vec2& operator-=(float right);
		Vec2& operator*=(float right);
		Vec2& operator/=(float right);
		Vec2 operator+() const;
		Vec2 operator-() const;
		Vec2 operator+(const Vec2& right) const;
		Vec2 operator-(const Vec2& right) const;
		Vec2 operator+(float right) const;
		Vec2 operator-(float right) const;
		Vec2 operator*(float right) const;
		Vec2 operator/(float right) const;
		bool operator==(const Vec2& right) const;
		bool operator!=(const Vec2& right) const;
		Vec2 operator&(const Vec2& right) const;    // cross
		float operator|(const Vec2& right) const;       // dot
		friend Vec2 operator*(float left, const Vec2& right);

		bool IsIdentity() const;
		float Dot(const Vec2& right) const;
		float Length() const;
		float LengthSq() const;
		float Accumulate(float scale = 1.0f) const;

		void Set(float x, float y);
		void Identify();
		void Diagonal(float v);
		Vec2 Abs() const;
		Vec2 Negative() const;
		Vec2 Normalize() const;

		static Vec2 Interpolate(const Vec2& left, const Vec2& right, float s);
		static Vec2 Lerp(const Vec2& left, const Vec2& right, float s);
		static Vec2 Minimize(const Vec2& left, const Vec2& right);
		static Vec2 Maximize(const Vec2& left, const Vec2& right);
		static Vec2 BaryCentric(const Vec2& v1, const Vec2& v2, const Vec2& v3, float f, float g);
		static Vec2 CatmullRom(const Vec2& v0, const Vec2& v1, const Vec2& v2, const Vec2& v3, float s);
		static Vec2 Hermite(const Vec2& v1, const Vec2& t1, const Vec2& v2, const Vec2& t2, float s);
		static Vec2 Cross(const Vec2& left, const Vec2& right);
		static float Dot(const Vec2& left, const Vec2& right);
		static bool Equals(const Vec2& left, const Vec2& right, float e = KM_EPSILON);

#if defined(__D3DX9MATH_H__)
		D3DXVECTOR2& ToD3DX() const;
#endif
	};

	// vector3
	struct Vec3 : public kVec3
	{
		Vec3() {}
		Vec3(float x, float y, float z);
		Vec3(const kVec3& right);
		Vec3(const kVec2& right, float z = 0.0f);

		Vec3& operator+=(const Vec3& right);
		Vec3& operator-=(const Vec3& right);
		Vec3& operator+=(float right);
		Vec3& operator-=(float right);
		Vec3& operator*=(float right);
		Vec3& operator/=(float right);
		Vec3 operator+() const;
		Vec3 operator-() const;
		Vec3 operator+(const Vec3& right) const;
		Vec3 operator-(const Vec3& right) const;
		Vec3 operator+(float right) const;
		Vec3 operator-(float right) const;
		Vec3 operator*(float right) const;
		Vec3 operator/(float right) const;
		bool operator==(const Vec3& right) const;
		bool operator!=(const Vec3& right) const;
		Vec3 operator&(const Vec3& right) const;    // cross
		float operator|(const Vec3& right) const;       // dot
		friend Vec3 operator*(float left, const Vec3& right);

		bool IsIdentity() const;
		float Dot(const Vec3& right) const;
		float LengthSq() const;
		float Length() const;
		float Yaw() const;
		float Accumulate(float scale = 1.0f) const;

		void Set(float x, float y, float z);
		void Set(const Vec2& v, float z = 0.0f);
		void Identify();
		void Diagonal(float v);
		void MinTest(const Vec3& v);
		void MaxTest(const Vec3& v);
		bool Reflect(const Vec3& in, const Vec3& dir);
		bool BetweenPoint(const Vec3& begin, const Vec3& end) const;
		bool IntersectPoint(const Plane& pl, const Vec3& v1, const Vec3& v2);
		bool IntersectLine(const Plane& pl, const Vec3& loc, const Vec3& dir);
		bool IntersectBetweenPoint(const Plane& pl, const Vec3& v1, const Vec3& v2);
		bool IntersectPlanes(const Plane& pl, const Plane& o1, const Plane& o2);
		Vec3 Abs() const;
		Vec3 Negative() const;
		Vec3 Normalize() const;
		Vec3 TransformCoordAddScale(const Vec3& v, const Mat4& m, float f);
		Vec3 TransformNormalAddScale(const Vec3& v, const Mat4& m, float f);

		static Vec3 Interpolate(const Vec3& left, const Vec3& right, float s);
		static Vec3 Lerp(const Vec3& left, const Vec3& right, float s);
		static Vec3 Minimize(const Vec3& left, const Vec3& right);
		static Vec3 Maximize(const Vec3& left, const Vec3& right);
		static Vec3 TransformCoord(const Vec3& left, const Mat4& right);
		static Vec3 TransformNormal(const Vec3& left, const Mat4& right);
		static Vec3 BuildRadiusBound(float r, const Mat4& right);
		static Vec3 Rotation(const Quat& q);
		static Vec3 Rotation(const Mat4& m);
		static Vec3 Rotation(const Quat& q, const Vec3& v);
		static Vec3 Direction(const Vec3& left, const Vec3& right);
		static Vec3 FormNorm(const Vec3& v1, const Vec3& v2, const Vec3& v3);
		static Vec3 BaryCentric(const Vec3& v1, const Vec3& v2, const Vec3& v3, float f, float g);
		static Vec3 CatmullRom(const Vec3& v0, const Vec3& v1, const Vec3& v2, const Vec3& v3, float s);
		static Vec3 Hermite(const Vec3& v1, const Vec3& t1, const Vec3& v2, const Vec3& t2, float s);
		static Vec3 ClosestPoint(const Line3& l, const Vec3& v);
		static Vec3 Cross(const Vec3& left, const Vec3& right);
		static float Radius(const Vec3& min, const Vec3& max);
		static float RadiusSq(const Vec3& min, const Vec3& max);
		static float Distance(const Vec3& left, const Vec3& right);
		static float DistanceSq(const Vec3& left, const Vec3& right);
		static float Dot(const Vec3& left, const Vec3& right);
		static bool Equals(const Vec3& left, const Vec3& right, float e = KM_EPSILON);

#if defined(__D3DX9MATH_H__)
		D3DXVECTOR3& ToD3DX() const;
#endif
	};

	// vector4
	struct Vec4 : public kVec4
	{
		Vec4() {};
		Vec4(float x, float y, float z, float w = 0.0f);
		Vec4(const kVec4& right);
		Vec4(const kVec3& v, float w = 0.0f);

		Vec4& operator+=(const Vec4& right);
		Vec4& operator-=(const Vec4& right);
		Vec4& operator+=(float right);
		Vec4& operator-=(float right);
		Vec4& operator*=(float right);
		Vec4& operator/=(float right);
		Vec4 operator+() const;
		Vec4 operator-() const;
		Vec4 operator+(const Vec4& right) const;
		Vec4 operator-(const Vec4& right) const;
		Vec4 operator+(float right) const;
		Vec4 operator-(float right) const;
		Vec4 operator*(float right) const;
		Vec4 operator/(float right) const;
		bool operator==(const Vec4& right) const;
		bool operator!=(const Vec4& right) const;
		float operator|(const Vec4& right) const;       // dot
		friend Vec4 operator*(float left, const Vec4& right);

		bool IsIdentity() const;
		float Dot(const Vec4& right) const;
		float LengthSq() const;
		float Length() const;
		float Accumulate(float scale = 1.0f) const;

		void Set(float x, float y, float z, float w);
		void Set(const Vec3& v, float w = 0.0f);
		void Identify();
		void Diagonal(float v);
		Vec4 Abs() const;
		Vec4 Negative() const;
		Vec4 Normalize() const;

		const float* ToPointer() const;

		static Vec4 Interpolate(const Vec4& left, const Vec4& right, float fElapsed);
		static Vec4 Lerp(const Vec4& left, const Vec4& right, float fLerp);
		static Vec4 Minimize(const Vec4& left, const Vec4& right);
		static Vec4 Maximize(const Vec4& left, const Vec4& right);
		static Vec4 Transform(const Vec3& left, const Mat4& right);
		static Vec4 Transform(const Vec4& left, const Mat4& right);
		static Vec4 Cross(const Vec4& v1, const Vec4& v2, const Vec4& v3);
		static float Dot(const Vec4& left, const Vec4& right);
		static bool Equals(const Vec4& left, const Vec4& right, float e = KM_EPSILON);

#if defined(__D3DX9MATH_H__)
		D3DXVECTOR4& ToD3DX() const;
#endif
	};

	// quaternion
	struct Quat : public kQuat
	{
		Quat() {};
		Quat(float x, float y, float z, float w = 1.0f);
		Quat(const kQuat& right);

		Quat& operator+=(const Quat& right);
		Quat& operator-=(const Quat& right);
		Quat& operator*=(const Quat& right);
		Quat& operator+=(float right);
		Quat& operator-=(float right);
		Quat& operator*=(float right);
		Quat& operator/=(float right);
		Quat operator+() const;
		Quat operator-() const;
		Quat operator!() const;
		Quat operator+(const Quat& right) const;
		Quat operator-(const Quat& right) const;
		Quat operator*(const Quat& right) const;
		Quat operator+(float right) const;
		Quat operator-(float right) const;
		Quat operator*(float right) const;
		Quat operator/(float right) const;
		bool operator==(const Quat& right) const;
		bool operator!=(const Quat& right) const;
		friend Quat operator*(float left, const Quat& right);

		bool IsIdentity() const;
		float Dot(const Quat& right) const;
		float LengthSq() const;
		float Length() const;

		void Set(float x, float y, float z, float w);
		void Set(const Vec3& v, float w = 1.0f);
		void Zero();
		void Identify();
		Quat Abs() const;
		Quat Negative() const;
		Quat Conjugate() const;
		Quat Inverse() const;
		Quat Normalize() const;
		Quat Exp() const;
		Quat Ln() const;

		static Quat Interpolate(const Quat& left, const Quat& right, float f);
		static Quat Slerp(const Quat& left, const Quat& right, float f);
		static Quat Squad(const Quat& q1, const Quat& q2, const Quat& q3, const Quat& q4, float t);
		static Quat Minimize(const Quat& left, const Quat& right);
		static Quat Maximize(const Quat& left, const Quat& right);
		static Quat Rotation(const Mat4& m);
		static Quat Rotation(const Vec3& v);
		static Quat Rotation(const Vec3& v, float angle);
		static Quat RotationX(float x);
		static Quat RotationY(float y);
		static Quat RotationZ(float z);
		static Quat BaryCentric(const Quat& q1, const Quat& q2, const Quat& q3, float f, float g);
		static Quat Cross(const Quat& v1, const Quat& v2, const Quat& v3);
		static float Dot(const Quat& left, const Quat& right);
		static bool Equals(const Quat& left, const Quat& right, float e = KM_EPSILON);
		static Quat ZeroQuaternion();
		static Quat IdentifyQuaternion();

#if defined(__D3DX9MATH_H__)
		D3DXQUATERNION& ToD3DX() const;
#endif
	};

	// matrix 4
	struct Mat4 : public kMat4
	{
		Mat4() {};
		Mat4(
			float _11, float _12, float _13, float _14,
			float _21, float _22, float _23, float _24,
			float _31, float _32, float _33, float _34,
			float _41, float _42, float _43, float _44);
		Mat4(const kMat4& right);

		float& operator()(kint row, kint col);
		float operator()(kint row, kint col) const;
		Mat4& operator+=(const Mat4& right);
		Mat4& operator-=(const Mat4& right);
		Mat4& operator*=(const Mat4& right);
		Mat4& operator*=(float right);
		Mat4& operator/=(float right);
		Mat4 operator+() const;
		Mat4 operator-() const;
		Mat4 operator!() const;
		Mat4 operator+(const Mat4& right) const;
		Mat4 operator-(const Mat4& right) const;
		Mat4 operator*(const Mat4& right) const;
		Mat4 operator*(float right) const;
		Mat4 operator/(float right) const;
		bool operator==(const Mat4& right) const;
		bool operator!=(const Mat4& right) const;
		friend Mat4 operator*(float left, const Mat4& right);

		bool IsIdentity() const;
		float Determinant() const;

		void Zero();
		void Identify();
		void Diagonal(float v);
		Mat4 Inverse() const;
		Mat4 Transpose() const;
		void ReplaceLocation(const Vec3& v);
		void ReplaceLocation(float x, float y, float z);
		void ReplaceAddLocation(const Vec3& v);
		void ReplaceAddLocation(float x, float y, float z);
		void ReplaceRotation(const Quat& q);
		void ReplaceRotation(float x, float y, float z, float w);
		void ReplaceScaling(const Vec3& v);
		void ReplaceScaling(float x, float y, float z);
		void ReplaceLerp(const Vec3& left, const Vec3& right, float scale);

		const float* ToPointer() const;

		static Mat4 Location(const Vec3& v);
		static Mat4 Location(float x, float y, float z);
		static Mat4 Scaling(const Vec3& v);
		static Mat4 Scaling(float x, float y, float z);
		static Mat4 Scaling(float f);
		static Mat4 Rotation(const Vec3& v);
		static Mat4 Rotation(const Quat& q);
		static Mat4 Rotation(float x, float y, float z);
		static Mat4 Rotation(float x, float y, float z, float w);
		static Mat4 RotationX(float f);
		static Mat4 RotationY(float f);
		static Mat4 RotationZ(float f);
		static Mat4 LookAtLH(const Vec3& eye, const Vec3& at, const Vec3& up);
		static Mat4 LookAtRH(const Vec3& eye, const Vec3& at, const Vec3& up);
		static Mat4 PerspectiveFovLH(float fov, float aspect, float znear, float zfar);
		static Mat4 PerspectiveFovRH(float fov, float aspect, float znear, float zfar);
		static Mat4 OrthoLH(float width, float height, float znear, float zfar);
		static Mat4 OrthoRH(float width, float height, float znear, float zfar);
		static Mat4 OrthoOffCenterLH(float l, float r, float b, float t, float zn, float zf);
		static Mat4 OrthoOffCenterRH(float l, float r, float b, float t, float zn, float zf);
		static Mat4 ViewPort(float x, float y, float width, float height);
		static Mat4 Shadow(const Vec4& light, const Plane& plane);
		static Mat4 Affine(const Vec3& scl, const Vec3& rotcenter, const Quat& rot, const Vec3& loc);
		static Mat4 Interpolate(const Mat4& left, const Mat4& right, float f);
		static Mat4 Transform(const Vec3& loc, const Quat& rot, const Vec3& scl);
		static Mat4 Transform(const Vec3& loc, const Vec3& rot, const Vec3& scl);
		static Mat4 Transform(const TrFm& tm);
		static bool Equals(const Mat4& left, const Mat4& right);
		static Mat4 ZeroMatrix();
		static Mat4 IdentifyMatrix();

#if defined(__D3DX9MATH_H__)
		D3DXMATRIX& ToD3DX() const;
#endif
	};

	// point
	struct Point : public kPt
	{
		Point() {}
		Point(kint x, kint y);
		Point(const kPt& right);

		void Set(kint x, kint y);
		void SetMm(kint min, kint max);

		bool OnPoint(kint value) const;
		float Aspect() const;

		Rect CenterRect(kint width, kint height);

#if defined(_WINDEF_)
		void Set(const POINT& pt);
#endif

		Vec2 ToVec2() const;
	};

	// rect
	struct Rect : public kRt
	{
		Rect() {}
		Rect(kint l, kint t, kint r, kint b);
		Rect(const kRt& right);
		Rect(const kPt& pos, const kPt& size);
		explicit Rect(const kQd& right);

		bool operator==(const Rect& right) const;
		bool operator!=(const Rect& right) const;

		void Zero();
		void Set(kint left, kint top, kint right, kint bottom);
		void SetSize(kint x, kint y, kint w, kint h);
		void SetCenter(kint screen_width, kint screen_height, kint width, kint height);
		void Move(kint x, kint y);
		void Expand(kint w, kint h);
		bool Intersect(const Rect& r1, const Rect& r2);

		Rect Inflate(kint x, kint y) const;
		Rect Deflate(kint x, kint y) const;
		Rect Offset(kint x, kint y) const;
		Rect Inflate(kint l, kint t, kint r, kint b) const;
		Rect Deflate(kint l, kint t, kint r, kint b) const;
		Rect Offset(kint l, kint t, kint r, kint b) const;
		Rect Center(kint screen_width, kint screen_height) const;

		kint Width() const;
		kint Height() const;
		float Aspect() const;
		bool OnPoint(const Point& pt) const;
		bool OnPoint(kint x, kint y) const;
		bool Intersect(const Rect& rt) const;
		bool Intersect(kint left, kint top, kint right, kint bottom) const;

#if defined(_WINDEF_)
		void Set(const RECT& rt);
#endif

		Point Location() const;
		Point Size() const;
		Point LeftTop() const;
		Point RightBottom() const;

		Quad ToQuad() const;
	};

	// Quad
	struct Quad : public kQd
	{
		Quad() {}
		Quad(float l, float t, float r, float b);
		Quad(const kQd& right);
		Quad(const kVec2& pos, const kVec2& size);
		explicit Quad(const kRt& right);

		void Zero();
		void Set(float left, float top, float right, float bottom);
		void Sized(float x, float y, float w, float h);
		bool Intersect(const Quad& r1, const Quad& r2);

		Quad Inflate(float x, float y) const;
		Quad Deflate(float x, float y) const;
		Quad Offset(float x, float y) const;
		Quad Inflate(float l, float t, float r, float b) const;
		Quad Deflate(float l, float t, float r, float b) const;
		Quad Offset(float l, float t, float r, float b) const;
		Quad Center(float screen_width, float screen_height) const;
		Quad Center(float screen_width, float screen_height, float offset_x, float offset_y) const;

		float Width() const;
		float Height() const;
		float Aspect() const;
		bool OnPoint(const Vec2& pt) const;
		bool OnPoint(float x, float y) const;

		static Quad ConvCoord(kint sx, kint sy, kint x, kint y, kint w, kint h);
		static Quad FillCoord();
		static Quad InvCoord();

		Vec2 Location() const;
		Vec2 Size() const;
		Vec2 LeftTop() const;
		Vec2 RightBottom() const;

		Rect ToRect() const;
	};

	// color
	struct Color : public kCr
	{
		Color() {}
		Color(float r, float g, float b, float a = 1.0f);
		Color(const kCr& right);
		explicit Color(kuint n);
		explicit Color(const kCu& cu);

		operator kuint() const;
		Color& operator+=(const Color& right);
		Color& operator-=(const Color& right);
		Color& operator*=(float right);
		Color& operator/=(float right);
		Color operator+() const;
		Color operator+(const Color& right) const;
		Color operator-(const Color& right) const;
		Color operator*(float right) const;
		Color operator/(float right) const;
		bool operator==(const Color& right) const;
		bool operator!=(const Color& right) const;

		kuint ToUint() const;
		kuint ToUintSimple() const;
		const float* ToPointer() const;

		void Set(float r, float g, float b, float a = 1.0f);
		void Set(kuint n);
		Color Negative() const;
		Color Contrast(float s) const;
		Color Saturation(float s) const;
		Color Brighten(float s) const;

		static Color Interpolate(const Color& left, const Color& right, float s);
		static Color Lerp(const Color& left, const Color& right, float s);
		static Color Modulate(const Color& left, const Color& right);
		static Color Minimize(const Color& left, const Color& right);
		static Color Maximize(const Color& left, const Color& right);
		static bool Equals(const Color& left, const Color& right, float e = KM_EPSILON);
	};

	// color value
	struct ColorValue : public kCu
	{
		ColorValue() {}
		ColorValue(kbyte r, kbyte g, kbyte b, kbyte a = 255);
		ColorValue(const kCu& right);
		explicit ColorValue(kuint n);
		explicit ColorValue(const kCr& cr);

		operator kuint() const;
		ColorValue& operator+=(const ColorValue& right);
		ColorValue& operator-=(const ColorValue& right);
		ColorValue& operator*=(float right);
		ColorValue& operator/=(float right);
		ColorValue operator+() const;
		ColorValue operator+(const ColorValue& right) const;
		ColorValue operator-(const ColorValue& right) const;
		ColorValue operator*(float right) const;
		ColorValue operator/(float right) const;
		bool operator==(const ColorValue& right) const;
		bool operator!=(const ColorValue& right) const;

		kuint ToUint() const;
		kuint ToBgra() const;
		const kbyte* ToPointer() const;

		void Set(kbyte r, kbyte g, kbyte b, kbyte a = 255);
		void Set(kuint n);
		ColorValue Negative() const;
		ColorValue Contrast(float s) const;
		ColorValue Saturation(float s) const;
		ColorValue Brighten(float s) const;

		static ColorValue Interpolate(const ColorValue& left, const ColorValue& right, float s);
		static ColorValue Lerp(const ColorValue& left, const ColorValue& right, float s);
		static ColorValue Modulate(const ColorValue& left, const ColorValue& right);
		static ColorValue Minimize(const ColorValue& left, const ColorValue& right);
		static ColorValue Maximize(const ColorValue& left, const ColorValue& right);
	};

	// plane
	struct Plane : public kPln
	{
		Plane() {}
		Plane(float a, float b, float c, float d = 1.0f);
		Plane(const kPln& right);

		float DotCoord(const Vec3& v) const;
		float Distance(const Vec3& v) const;
		kint RelationPoint(const Vec3& v) const;

		void Identify();
		void Set(float a, float b, float c, float d);
		void Set(const Vec3& v, float d = 1.0f);
		Plane Normalize() const;
		Plane ReverseNormalize() const;
		bool TestIntersectPlane(Vec3* loc, Vec3* dir, const Plane& pl) const;
		bool IntersectPlane(const Plane& o1, const Plane& o2) const;
		float IntersectLine(const Vec3& v1, const Vec3& v2) const;

		static Plane Transform(const Plane& left, const Mat4& right);
		static Plane FromPoints(const Vec3& v1, const Vec3& v2, const Vec3& v3);
		static Plane FromPointNormal(const Vec3& v, const Vec3& n);
	};

	// line 3
	struct Line3 : public kLn3
	{
		Line3() {}
		Line3(float bx, float by, float bz, float ex, float ey, float ez);
		Line3(const kVec3& begin, const kVec3& end);
		Line3(const kLn3& right);

		float LengthSq() const;
		float Length() const;
		Vec3 Center() const;
		Vec3 Vector() const;
		Vec3 ClosestPoint(const Vec3& v) const;
		bool BetweenPoint(const Vec3& v) const;

		void Set(float bx, float by, float bz, float ex, float ey, float ez);
		void Set(const Vec3& begin, const Vec3& end);
		bool IntersectSphere(const Vec3& org, float radius, float* dist = 0) const;

		const Vec3& Begin() const;
		const Vec3& End() const;
		Vec3& Begin();
		Vec3& End();
	};

	// transform
	struct TrFm /*: public hbTrfm*/
	{
		Vec3                loc;
		Quat                rot;
		Vec3                scl;

		TrFm() {}
		TrFm(const kVec3& loc, const kQuat& rot, const kVec3& scl);

		void Identify();
	};

	// vech2
	struct VecH2 : public kVecH2
	{
		VecH2() {}
		VecH2(float x, float y);
		VecH2(const kVec2& v);

		void Set(float x, float y);
		void Set(const Vec2& v);
		Vec2 ToVec2() const;

		static bool Equals(const VecH2& left, const VecH2& right);
	};

	// vech3
	struct VecH3 : public kVecH3
	{
		VecH3() {}
		VecH3(float x, float y, float z);
		VecH3(const kVec3& v);

		void Set(float x, float y, float z);
		void Set(const Vec3& v);
		Vec3 ToVec3() const;

		static bool Equals(const VecH3& left, const VecH3& right);
	};

	// vech4
	struct VecH4 : public kVecH4
	{
		VecH4() {}
		VecH4(float x, float y, float z, float w);
		VecH4(const kVec4& v);

		void Set(float x, float y, float z, float w);
		void Set(const Vec4& v);
		Vec4 ToVec4() const;

		static bool Equals(const VecH4& left, const VecH4& right);
	};

	// color blend
	struct BlendColor
	{
		Color           color[3];
		float           adv;
		bool            loop;
		kbyte          dir;

		BlendColor();
		BlendColor(const kCr& c1, const kCr& c2, bool loop = false);

		void Reset(bool loop = false);
		void Reset(const Color& c1, const Color& c2, bool loop = false);

		void Update(float adv, float speed);
		const Color& Value();
	};
}





















//////////////////////////////////////////////////////////////////////////
// type implement
namespace tpl
{
	// vector 2
	inline Vec2::Vec2(float x, float y)
	{
		this->x = x;
		this->y = y;
	}

	inline Vec2::Vec2(const kVec2& right)
	{
		this->x = right.x;
		this->y = right.y;
	}

	inline Vec2& Vec2::operator+=(const Vec2& right)
	{
		x += right.x;
		y += right.y;
		return *this;
	}

	inline Vec2& Vec2::operator-=(const Vec2& right)
	{
		x -= right.x;
		y -= right.y;
		return *this;
	}

	inline Vec2& Vec2::operator+=(float right)
	{
		x += right;
		y += right;
		return *this;
	}

	inline Vec2& Vec2::operator-=(float right)
	{
		x -= right;
		y -= right;
		return *this;
	}

	inline Vec2& Vec2::operator*=(float right)
	{
		x *= right;
		y *= right;
		return *this;
	}

	inline Vec2& Vec2::operator/=(float right)
	{
		x /= right;
		y /= right;
		return *this;
	}

	inline Vec2 Vec2::operator+() const
	{
		return *this;
	}

	inline Vec2 Vec2::operator-() const
	{
		return Vec2(-x, -y);
	}

	inline Vec2 Vec2::operator+(const Vec2& right) const
	{
		return Vec2(x + right.x, y + right.y);
	}

	inline Vec2 Vec2::operator-(const Vec2& right) const
	{
		return Vec2(x - right.x, y - right.y);
	}

	inline Vec2 Vec2::operator+(float right) const
	{
		return Vec2(x + right, y + right);
	}

	inline Vec2 Vec2::operator-(float right) const
	{
		return Vec2(x - right, y - right);
	}

	inline Vec2 Vec2::operator*(float right) const
	{
		return Vec2(x * right, y * right);
	}

	inline Vec2 Vec2::operator/(float right) const
	{
		return Vec2(x / right, y / right);
	}

	inline bool Vec2::operator==(const Vec2& right) const
	{
		return
			k_eq(x, right.x) &&
			k_eq(y, right.y);
	}

	inline bool Vec2::operator!=(const Vec2& right) const
	{
		return
			!k_eq(x, right.x) ||
			!k_eq(y, right.y);
	}

	inline Vec2 Vec2::operator&(const Vec2& right) const    // cross
	{
		return Vec2(
			y * right.x - x * right.y,
			x * right.y - y * right.x);
	}

	inline float Vec2::operator|(const Vec2& right) const       // dot
	{
		return x * right.x + y * right.y;
	}

	inline Vec2 operator*(float left, const Vec2& right)
	{
		return Vec2(left * right.x, left * right.y);
	}

	inline bool Vec2::IsIdentity() const
	{
		return k_eq(x, 0.0f) && k_eq(y, 0.0f);
	}

	inline float Vec2::Dot(const Vec2& right) const
	{
		return x * right.x + y * right.y;
	}

	inline float Vec2::Length() const
	{
		return k_sqrt(x * x + y * y);
	}

	inline float Vec2::LengthSq() const
	{
		return x * x + y * y;
	}

	inline float Vec2::Accumulate(float scale) const
	{
		return (x + y) * scale;
	}

	inline void Vec2::Set(float x, float y)
	{
		this->x = x;
		this->y = y;
	}

	inline void Vec2::Identify()
	{
		x = 0.0f;
		y = 0.0f;
	}

	inline void Vec2::Diagonal(float v)
	{
		x = v;
		y = v;
	}

	inline Vec2 Vec2::Abs() const
	{
		return Vec2(k_abs(x), k_abs(y));
	}

	inline Vec2 Vec2::Negative() const
	{
		return Vec2(1.0f - x, 1.0f - y);
	}

	inline Vec2 Vec2::Normalize() const
	{
		Vec2 t;
		k_vec2_norm(&t, this);
		return t;
	}

	inline Vec2 Vec2::Interpolate(const Vec2& left, const Vec2& right, float s)
	{
		float f = 1.0f - s;
		return Vec2(
			right.x * f + left.x * s,
			right.y * f + left.y * s);
	}

	inline Vec2 Vec2::Lerp(const Vec2& left, const Vec2& right, float s)
	{
		return Vec2(
			left.x + s * (right.x - left.x),
			left.y + s * (right.y - left.y));
	}

	inline Vec2 Vec2::Minimize(const Vec2& left, const Vec2& right)
	{
		return Vec2(
			left.x < right.x ? left.x : right.x,
			left.y < right.y ? left.y : right.y);
	}

	inline Vec2 Vec2::Maximize(const Vec2& left, const Vec2& right)
	{
		return Vec2(
			left.x > right.x ? left.x : right.x,
			left.y > right.y ? left.y : right.y);
	}

	inline Vec2 Vec2::BaryCentric(const Vec2& v1, const Vec2& v2, const Vec2& v3, float f, float g)
	{
		Vec2 t;
		k_vec2_bary_centric(&t, &v1, &v2, &v3, f, g);
		return t;
	}

	inline Vec2 Vec2::CatmullRom(const Vec2& v0, const Vec2& v1, const Vec2& v2, const Vec2& v3, float s)
	{
		Vec2 t;
		k_vec2_catmull_rom(&t, &v0, &v1, &v2, &v3, s);
		return t;
	}

	inline Vec2 Vec2::Hermite(const Vec2& v1, const Vec2& t1, const Vec2& v2, const Vec2& t2, float s)
	{
		Vec2 t;
		k_vec2_hermite(&t, &v1, &t1, &v2, &t2, s);
		return t;
	}

	inline Vec2 Vec2::Cross(const Vec2& left, const Vec2& right)
	{
		return Vec2(
			left.y * right.x - left.x * right.y,
			left.x * right.y - left.y * right.x);
	}

	inline float Vec2::Dot(const Vec2& left, const Vec2& right)
	{
		return left.x * right.x + left.y * right.y;
	}

	inline bool Vec2::Equals(const Vec2& left, const Vec2& right, float e)
	{
		return
			k_epsilon(left.x, right.x, e) &&
			k_epsilon(left.y, right.y, e);
	}

#if defined(__D3DX9MATH_H__)
	inline D3DXVECTOR2& Vec2::ToD3DX() const
	{
		return *(D3DXVECTOR2*)this;
	}
#endif


	// vector 3
	inline Vec3::Vec3(float x, float y, float z)
	{
		this->x = x;
		this->y = y;
		this->z = z;
	}

	inline Vec3::Vec3(const kVec3& right)
	{
		x = right.x;
		y = right.y;
		z = right.z;
	}

	inline Vec3::Vec3(const kVec2& right, float z/*=0.0f*/)
	{
		x = right.x;
		y = right.y;
		this->z = z;
	}

	inline Vec3& Vec3::operator+=(const Vec3& right)
	{
		x += right.x;
		y += right.y;
		z += right.z;
		return *this;
	}

	inline Vec3& Vec3::operator-=(const Vec3& right)
	{
		x -= right.x;
		y -= right.y;
		z -= right.z;
		return *this;
	}

	inline Vec3& Vec3::operator+=(float right)
	{
		x += right;
		y += right;
		z += right;
		return *this;
	}

	inline Vec3& Vec3::operator-=(float right)
	{
		x -= right;
		y -= right;
		z -= right;
		return *this;
	}

	inline Vec3& Vec3::operator*=(float right)
	{
		x *= right;
		y *= right;
		z *= right;
		return *this;
	}

	inline Vec3& Vec3::operator/=(float right)
	{
		x /= right;
		y /= right;
		z /= right;
		return *this;
	}

	inline Vec3 Vec3::operator+() const
	{
		return *this;
	}

	inline Vec3 Vec3::operator-() const
	{
		return Vec3(-x, -y, -z);
	}

	inline Vec3 Vec3::operator+(const Vec3& right) const
	{
		return Vec3(x + right.x, y + right.y, z + right.z);
	}

	inline Vec3 Vec3::operator-(const Vec3& right) const
	{
		return Vec3(x - right.x, y - right.y, z - right.z);
	}

	inline Vec3 Vec3::operator+(float right) const
	{
		return Vec3(x + right, y + right, z + right);
	}

	inline Vec3 Vec3::operator-(float right) const
	{
		return Vec3(x - right, y - right, z - right);
	}

	inline Vec3 Vec3::operator*(float right) const
	{
		return Vec3(x * right, y * right, z * right);
	}

	inline Vec3 Vec3::operator/(float right) const
	{
		return Vec3(x / right, y / right, z / right);
	}

	inline bool Vec3::operator==(const Vec3& right) const
	{
		return
			k_eq(x, right.x) &&
			k_eq(y, right.y) &&
			k_eq(z, right.z);
	}

	inline bool Vec3::operator!=(const Vec3& right) const
	{
		return
			!k_eq(x, right.x) ||
			!k_eq(y, right.y) ||
			!k_eq(z, right.z);
	}

	inline Vec3 Vec3::operator&(const Vec3& right) const    // cross
	{
		return Vec3(
			y * right.z - z * right.y,
			z * right.x - x * right.z,
			x * right.y - y * right.x);
	}

	inline float Vec3::operator|(const Vec3& right) const// dot
	{
		return x * right.x + y * right.y + z * right.z;
	}

	inline Vec3 operator*(float left, const Vec3& right)
	{
		return Vec3(left * right.x, left * right.y, left * right.z);
	}

	inline bool Vec3::IsIdentity() const
	{
		return x == 0.0f && y == 0.0f && z == 0.0f;
	}

	inline float Vec3::Dot(const Vec3& right) const
	{
		return x * right.x + y * right.y + z * right.z;
	}

	inline float Vec3::LengthSq() const
	{
		return x * x + y * y + z * z;
	}

	inline float Vec3::Length() const
	{
		return k_sqrt(x * x + y * y + z * z);
	}

	inline float Vec3::Yaw() const
	{
		return k_vec3_yaw(this);
	}

	inline float Vec3::Accumulate(float scale/*=1.0f*/) const
	{
		return (x + y + z) * scale;
	}

	inline void Vec3::Set(float x, float y, float z)
	{
		this->x = x;
		this->y = y;
		this->z = z;
	}

	inline void Vec3::Set(const Vec2& v, float z)
	{
		this->x = v.x;
		this->y = v.y;
		this->z = z;
	}

	inline void Vec3::Identify()
	{
		x = 0.0f;
		y = 0.0f;
		z = 0.0f;
	}

	inline void Vec3::Diagonal(float v)
	{
		x = v;
		y = v;
		z = v;
	}

	inline void Vec3::MinTest(const Vec3& v)
	{
		if (x > v.x) x = v.x;

		if (y > v.y) y = v.y;

		if (z > v.z) z = v.z;
	}

	inline void Vec3::MaxTest(const Vec3& v)
	{
		if (x < v.x) x = v.x;

		if (y < v.y) y = v.y;

		if (z < v.z) z = v.z;
	}

	inline bool Vec3::Reflect(const Vec3& in, const Vec3& dir)
	{
		return k_vec3_reflect(this, &in, &dir) != 0;
	}

	inline bool Vec3::BetweenPoint(const Vec3& begin, const Vec3& end) const
	{
		return k_vec3_between(this, &begin, &end) != 0;
	}

	inline bool Vec3::IntersectPoint(const Plane& pl, const Vec3& v1, const Vec3& v2)
	{
		return k_vec3_intersect_pt(this, &pl, &v1, &v2) != 0;
	}

	inline bool Vec3::IntersectLine(const Plane& pl, const Vec3& loc, const Vec3& dir)
	{
		return k_vec3_intersect_line(this, &pl, &loc, &dir) != 0;
	}

	inline bool Vec3::IntersectBetweenPoint(const Plane& pl, const Vec3& v1, const Vec3& v2)
	{
		return k_vec3_intersect_between_pt(this, &pl, &v1, &v2) != 0;
	}

	inline bool Vec3::IntersectPlanes(const Plane& pl, const Plane& o1, const Plane& o2)
	{
		return k_vec3_intersect_planes(this, &pl, &o1, &o2) != 0;
	}

	inline Vec3 Vec3::Abs() const
	{
		return Vec3(k_abs(x), k_abs(y), k_abs(z));
	}

	inline Vec3 Vec3::Negative() const
	{
		return Vec3(1.0f - x, 1.0f - y, 1.0f - z);
	}

	inline Vec3 Vec3::Normalize() const
	{
		Vec3 t;
		k_vec3_norm(&t, this);
		return t;
	}

	inline Vec3 Vec3::Interpolate(const Vec3& left, const Vec3& right, float s)
	{
		Vec3 t;
		k_vec3_interpolate(&t, &left, &right, s);
		return t;
	}

	inline Vec3 Vec3::Lerp(const Vec3& left, const Vec3& right, float s)
	{
		Vec3 t;
		k_vec3_lerp(&t, &left, &right, s);
		return t;
	}

	inline Vec3 Vec3::Minimize(const Vec3& left, const Vec3& right)
	{
		return Vec3(
			left.x < right.x ? left.x : right.x,
			left.y < right.y ? left.y : right.y,
			left.z < right.z ? left.z : right.z);
	}

	inline Vec3 Vec3::Maximize(const Vec3& left, const Vec3& right)
	{
		return Vec3(
			left.x > right.x ? left.x : right.x,
			left.y > right.y ? left.y : right.y,
			left.z > right.z ? left.z : right.z);
	}

	inline Vec3 Vec3::TransformCoord(const Vec3& left, const Mat4& right)
	{
		return Vec3(
			left.x * right._11 + left.y * right._21 + left.z * right._31 + right._41,
			left.x * right._12 + left.y * right._22 + left.z * right._32 + right._42,
			left.x * right._13 + left.y * right._23 + left.z * right._33 + right._43);
	}

	inline Vec3 Vec3::TransformNormal(const Vec3& left, const Mat4& right)
	{
		return Vec3(
			left.x * right._11 + left.y * right._21 + left.z * right._31,
			left.x * right._12 + left.y * right._22 + left.z * right._32,
			left.x * right._13 + left.y * right._23 + left.z * right._33);
	}

	inline Vec3 Vec3::BuildRadiusBound(float v, const Mat4& right)
	{
		return Vec3(
			k_abs(v * right._11 + v * right._21 + v * right._31),
			k_abs(v * right._12 + v * right._22 + v * right._32),
			k_abs(v * right._13 + v * right._23 + v * right._33));
	}

	inline Vec3 Vec3::TransformCoordAddScale(const Vec3& left, const Mat4& right, float f)
	{
		return Vec3(
			(left.x * right._11 + left.y * right._21 + left.z * right._31 + right._41) * f + this->x,
			(left.x * right._12 + left.y * right._22 + left.z * right._32 + right._42) * f + this->y,
			(left.x * right._13 + left.y * right._23 + left.z * right._33 + right._43) * f + this->z);
	}

	inline Vec3 Vec3::TransformNormalAddScale(const Vec3& left, const Mat4& right, float f)
	{
		return Vec3(
			(left.x * right._11 + left.y * right._21 + left.z * right._31) * f + this->x,
			(left.x * right._12 + left.y * right._22 + left.z * right._32) * f + this->y,
			(left.x * right._13 + left.y * right._23 + left.z * right._33) * f + this->z);
	}

	inline Vec3 Vec3::Rotation(const Quat& q)
	{
		Vec3 t;
		k_vec3_rot_quat(&t, &q);
		return t;
	}

	inline Vec3 Vec3::Rotation(const Mat4& m)
	{
		Vec3 t;
		k_vec3_rot_mat4(&t, &m);
		return t;
	}

	inline Vec3 Vec3::Rotation(const Quat& q, const Vec3& v)
	{
		Vec3 t;
		k_vec3_rot_quat_vec3(&t, &q, &v);
		return t;
	}

	inline Vec3 Vec3::Direction(const Vec3& left, const Vec3& right)
	{
		return (left - right).Normalize();
	}

	inline Vec3 Vec3::FormNorm(const Vec3& v1, const Vec3& v2, const Vec3& v3)
	{
		Vec3 t;
		k_vec3_form_norm(&t, &v1, &v2, &v3);
		return t;
	}

	inline Vec3 Vec3::BaryCentric(const Vec3& v1, const Vec3& v2, const Vec3& v3, float f, float g)
	{
		Vec3 t;
		k_vec3_bary_centric(&t, &v1, &v2, &v3, f, g);
		return t;
	}

	inline Vec3 Vec3::CatmullRom(const Vec3& v0, const Vec3& v1, const Vec3& v2, const Vec3& v3, float s)
	{
		Vec3 t;
		k_vec3_catmull_rom(&t, &v0, &v1, &v2, &v3, s);
		return t;
	}

	inline Vec3 Vec3::Hermite(const Vec3& v1, const Vec3& t1, const Vec3& v2, const Vec3& t2, float s)
	{
		Vec3 t;
		k_vec3_hermite(&t, &v1, &t1, &v2, &t2, s);
		return t;
	}

	inline Vec3 Vec3::ClosestPoint(const Line3& l, const Vec3& v)
	{
		Vec3 t;
		k_vec3_cpt_line(&t, &l, &v);
		return t;
	}

	inline Vec3 Vec3::Cross(const Vec3& left, const Vec3& right)
	{
		return Vec3(
			left.y * right.z - left.z * right.y,
			left.z * right.x - left.x * right.z,
			left.x * right.y - left.y * right.x);
	}

	inline float Vec3::Radius(const Vec3& min, const Vec3& max)
	{
		Vec3 t = ((min + max) * 0.5f) - min;
		return k_sqrt(t.x * t.x + t.y * t.y + t.z * t.z);
	}

	inline float Vec3::RadiusSq(const Vec3& min, const Vec3& max)
	{
		Vec3 t = ((min + max) * 0.5f) - min;
		return t.x * t.x + t.y * t.y + t.z * t.z;
	}

	inline float Vec3::Distance(const Vec3& left, const Vec3& right)
	{
		Vec3 t = left - right;
		return k_sqrt(t.x * t.x + t.y * t.y + t.z * t.z);
	}

	inline float Vec3::DistanceSq(const Vec3& left, const Vec3& right)
	{
		Vec3 t = left - right;
		return t.x * t.x + t.y * t.y + t.z * t.z;
	}

	inline float Vec3::Dot(const Vec3& left, const Vec3& right)
	{
		return left.x * right.x + left.y * right.y + left.z * right.z;
	}

	inline bool Vec3::Equals(const Vec3& left, const Vec3& right, float e/*=KM_EPSILON*/)
	{
		return
			k_epsilon(left.x, right.x, e) &&
			k_epsilon(left.y, right.y, e) &&
			k_epsilon(left.z, right.z, e);
	}

#if defined(__D3DX9MATH_H__)
	inline D3DXVECTOR3& Vec3::ToD3DX() const
	{
		return *(D3DXVECTOR3*)this;
	}
#endif


	// vector 4
	inline Vec4::Vec4(float x, float y, float z, float w/*=0.0f*/)
	{
		this->x = x;
		this->y = y;
		this->z = z;
		this->w = w;
	}

	inline Vec4::Vec4(const kVec4& right)
	{
		this->x = right.x;
		this->y = right.y;
		this->z = right.z;
		this->w = right.w;
	}

	inline Vec4::Vec4(const kVec3& v, float w/*=0.0f*/)
	{
		this->x = v.x;
		this->y = v.y;
		this->z = v.z;
		this->w = w;
	}

	inline Vec4& Vec4::operator+=(const Vec4& right)
	{
		x += right.x;
		y += right.y;
		z += right.z;
		w += right.z;
		return *this;
	}

	inline Vec4& Vec4::operator-=(const Vec4& right)
	{
		x -= right.x;
		y -= right.y;
		z -= right.z;
		w -= right.z;
		return *this;
	}

	inline Vec4& Vec4::operator+=(float right)
	{
		x += right;
		y += right;
		z += right;
		w += right;
		return *this;
	}

	inline Vec4& Vec4::operator-=(float right)
	{
		x -= right;
		y -= right;
		z -= right;
		w -= right;
		return *this;
	}

	inline Vec4& Vec4::operator*=(float right)
	{
		x *= right;
		y *= right;
		z *= right;
		w *= right;
		return *this;
	}

	inline Vec4& Vec4::operator/=(float right)
	{
		x /= right;
		y /= right;
		z /= right;
		w /= right;
		return *this;
	}

	inline Vec4 Vec4::operator+() const
	{
		return *this;
	}

	inline Vec4 Vec4::operator-() const
	{
		return Vec4(-x, -y, -z, -w);
	}

	inline Vec4 Vec4::operator+(const Vec4& right) const
	{
		return Vec4(x + right.x, y + right.y, z + right.z, w + right.w);
	}

	inline Vec4 Vec4::operator-(const Vec4& right) const
	{
		return Vec4(x - right.x, y - right.y, z - right.z, w - right.w);
	}

	inline Vec4 Vec4::operator+(float right) const
	{
		return Vec4(x + right, y + right, z + right, w + right);
	}

	inline Vec4 Vec4::operator-(float right) const
	{
		return Vec4(x - right, y - right, z - right, w - right);
	}

	inline Vec4 Vec4::operator*(float right) const
	{
		return Vec4(x * right, y * right, z * right, w * right);
	}

	inline Vec4 Vec4::operator/(float right) const
	{
		return Vec4(x / right, y / right, z / right, w / right);
	}

	inline bool Vec4::operator==(const Vec4& right) const
	{
		return
			k_eq(x, right.x) &&
			k_eq(y, right.y) &&
			k_eq(z, right.z) &&
			k_eq(w, right.w);
	}

	inline bool Vec4::operator!=(const Vec4& right) const
	{
		return
			!k_eq(x, right.x) ||
			!k_eq(y, right.y) ||
			!k_eq(z, right.z) ||
			!k_eq(w, right.w);
	}

	inline float Vec4::operator|(const Vec4& right) const       // dot
	{
		return x * right.x + y * right.y + z * right.z + w * right.w;
	}

	inline Vec4 operator*(float left, const Vec4& right)
	{
		return Vec4(left * right.x, left * right.y, left * right.z, left * right.w);
	}

	inline bool Vec4::IsIdentity() const
	{
		return x == 0.0f && y == 0.0f && z == 0.0f && w == 0.0f;
	}

	inline float Vec4::Dot(const Vec4& right) const
	{
		return x * right.x + y * right.y + z * right.z + w * right.w;
	}

	inline float Vec4::LengthSq() const
	{
		return x * x + y * y + z * z + w * w;
	}

	inline float Vec4::Length() const
	{
		return k_sqrt(x * x + y * y + z * z + w * w);
	}

	inline float Vec4::Accumulate(float scale/*=1.0f*/) const
	{
		return (x + y + z + w) * scale;
	}

	inline void Vec4::Set(float x, float y, float z, float w)
	{
		this->x = x;
		this->y = y;
		this->z = z;
		this->w = w;
	}

	inline void Vec4::Set(const Vec3& v, float w/*=0.0f*/)
	{
		this->x = v.x;
		this->y = v.y;
		this->z = v.z;
		this->w = w;
	}

	inline void Vec4::Identify()
	{
		x = 0.0f;
		y = 0.0f;
		z = 0.0f;
		w = 0.0f;
	}

	inline void Vec4::Diagonal(float v)
	{
		x = v;
		y = v;
		z = v;
		w = v;
	}

	inline Vec4 Vec4::Abs() const
	{
		return Vec4(
			k_abs(x),
			k_abs(y),
			k_abs(z),
			k_abs(w));
	}

	inline Vec4 Vec4::Negative() const
	{
		return Vec4(
			1.0f - x,
			1.0f - y,
			1.0f - z,
			1.0f - w);
	}

	inline Vec4 Vec4::Normalize() const
	{
		Vec4 t;
		k_vec4_norm(&t, this);
		return t;
	}

	inline const float* Vec4::ToPointer() const
	{
		return (float*)this;
	}

	inline Vec4 Vec4::Interpolate(const Vec4& left, const Vec4& right, float fElapsed)
	{
		Vec4 t;
		k_vec4_interpolate(&t, &left, &right, fElapsed);
		return t;
	}

	inline Vec4 Vec4::Lerp(const Vec4& left, const Vec4& right, float fLerp)
	{
		Vec4 t;
		k_vec4_lerp(&t, &left, &right, fLerp);
		return t;
	}

	inline Vec4 Vec4::Minimize(const Vec4& left, const Vec4& right)
	{
		return Vec4(
			left.x < right.x ? left.x : right.x,
			left.y < right.y ? left.y : right.y,
			left.z < right.z ? left.z : right.z,
			left.w < right.w ? left.w : right.w);
	}

	inline Vec4 Vec4::Maximize(const Vec4& left, const Vec4& right)
	{
		return Vec4(
			left.x > right.x ? left.x : right.x,
			left.y > right.y ? left.y : right.y,
			left.z > right.z ? left.z : right.z,
			left.w > right.w ? left.w : right.w);
	}

	inline Vec4 Vec4::Transform(const Vec3& left, const Mat4& right)
	{
		return Vec4(
			left.x * right._11 + left.y * right._21 + left.z * right._31 + right._41,
			left.x * right._12 + left.y * right._22 + left.z * right._32 + right._42,
			left.x * right._13 + left.y * right._23 + left.z * right._33 + right._43,
			left.x * right._14 + left.y * right._24 + left.z * right._34 + right._44);
	}

	inline Vec4 Vec4::Transform(const Vec4& left, const Mat4& right)
	{
		return Vec4(
			left.x * right._11 + left.y * right._21 + left.z * right._31 + left.w * right._41,
			left.x * right._12 + left.y * right._22 + left.z * right._32 + left.w * right._42,
			left.x * right._13 + left.y * right._23 + left.z * right._33 + left.w * right._43,
			left.x * right._14 + left.y * right._24 + left.z * right._34 + left.w * right._44);
	}

	inline Vec4 Vec4::Cross(const Vec4& v1, const Vec4& v2, const Vec4& v3)
	{
		Vec4 t;
		k_vec4_cross(&t, &v1, &v2, &v3);
		return t;
	}

	inline float Vec4::Dot(const Vec4& left, const Vec4& right)
	{
		return left.x * right.x + left.y * right.y + left.z * right.z + left.w * right.w;
	}

	inline bool Vec4::Equals(const Vec4& left, const Vec4& right, float e/*=KM_EPSILON*/)
	{
		return
			k_epsilon(left.x, right.x, e) &&
			k_epsilon(left.y, right.y, e) &&
			k_epsilon(left.z, right.z, e) &&
			k_epsilon(left.w, right.w, e);
	}

#if defined(__D3DX9MATH_H__)
	inline D3DXVECTOR4& Vec4::ToD3DX() const
	{
		return *(D3DXVECTOR4*)this;
	}
#endif


	// quaternion
	inline Quat::Quat(float x, float y, float z, float w/*=1.0f*/)
	{
		this->x = x;
		this->y = y;
		this->z = z;
		this->w = w;
	}

	inline Quat::Quat(const kQuat& right)
	{
		this->x = right.x;
		this->y = right.y;
		this->z = right.z;
		this->w = right.w;
	}

	inline Quat& Quat::operator+=(const Quat& right)
	{
		x += right.x;
		y += right.y;
		z += right.z;
		w += right.w;
		return *this;
	}

	inline Quat& Quat::operator-=(const Quat& right)
	{
		x -= right.x;
		y -= right.y;
		z -= right.z;
		w -= right.w;
		return *this;
	}

	inline Quat& Quat::operator*=(const Quat& right)
	{
		k_quat_mul(this, this, &right);
		return *this;
	}

	inline Quat& Quat::operator+=(float right)
	{
		x += right;
		y += right;
		z += right;
		w += right;
		return *this;
	}

	inline Quat& Quat::operator-=(float right)
	{
		x -= right;
		y -= right;
		z -= right;
		w -= right;
		return *this;
	}

	inline Quat& Quat::operator*=(float right)
	{
		x *= right;
		y *= right;
		z *= right;
		w *= right;
		return *this;
	}

	inline Quat& Quat::operator/=(float right)
	{
		x /= right;
		y /= right;
		z /= right;
		w /= right;
		return *this;
	}

	inline Quat Quat::operator+() const
	{
		return *this;
	}

	inline Quat Quat::operator-() const
	{
		return Quat(-x, -y, -z, -w);
	}

	inline Quat Quat::operator!() const
	{
		Quat t;
		k_quat_inv(&t, this);
		return t;
	}

	inline Quat Quat::operator+(const Quat& right) const
	{
		return Quat(
			x + right.x,
			y + right.y,
			z + right.z,
			w + right.w);
	}

	inline Quat Quat::operator-(const Quat& right) const
	{
		return Quat(
			x - right.x,
			y - right.y,
			z - right.z,
			w - right.w);
	}

	inline Quat Quat::operator*(const Quat& right) const
	{
		Quat t;
		k_quat_mul(&t, this, &right);
		return t;
	}

	inline Quat Quat::operator+(float right) const
	{
		return Quat(x + right, y + right, z + right, w + right);
	}

	inline Quat Quat::operator-(float right) const
	{
		return Quat(x - right, y - right, z - right, w - right);
	}

	inline Quat Quat::operator*(float right) const
	{
		return Quat(x * right, y * right, z * right, w * right);
	}

	inline Quat Quat::operator/(float right) const
	{
		return Quat(x / right, y / right, z / right, w / right);
	}

	inline bool Quat::operator==(const Quat& right) const
	{
		return
			k_eq(x, right.x) &&
			k_eq(y, right.y) &&
			k_eq(z, right.z) &&
			k_eq(w, right.w);
	}

	inline bool Quat::operator!=(const Quat& right) const
	{
		return
			!k_eq(x, right.x) ||
			!k_eq(y, right.y) ||
			!k_eq(z, right.z) ||
			!k_eq(w, right.w);
	}

	inline Quat operator*(float left, const Quat& right)
	{
		return Quat(left * right.x, left * right.y, left * right.z, left * right.w);
	}

	inline bool Quat::IsIdentity() const
	{
		return x == 0.0f && y == 0.0f && z == 0.0f && w == 1.0f;
	}

	inline float Quat::Dot(const Quat& right) const
	{
		return x * right.x + y * right.y + z * right.z + w * right.w;
	}

	inline float Quat::LengthSq() const
	{
		return x * x + y * y + z * z + w * w;
	}

	inline float Quat::Length() const
	{
		return k_sqrt(x * x + y * y + z * z + w * w);
	}

	inline void Quat::Set(float x, float y, float z, float w)
	{
		this->x = x;
		this->y = y;
		this->z = z;
		this->w = w;
	}

	inline void Quat::Set(const Vec3& v, float w/*=1.0f*/)
	{
		this->x = v.x;
		this->y = v.y;
		this->z = v.z;
		this->w = w;
	}

	inline void Quat::Zero()
	{
		x = 0.0f;
		y = 0.0f;
		z = 0.0f;
		w = 0.0f;
	}

	inline void Quat::Identify()
	{
		x = 0.0f;
		y = 0.0f;
		z = 0.0f;
		w = 1.0f;
	}

	inline Quat Quat::Abs() const
	{
		return Quat(
			k_abs(x),
			k_abs(y),
			k_abs(z),
			k_abs(w));
	}

	inline Quat Quat::Negative() const
	{
		return Quat(
			1.0f - x,
			1.0f - y,
			1.0f - z,
			1.0f - w);
	}

	inline Quat Quat::Conjugate() const
	{
		return Quat(-x, -y, -z, w);
	}

	inline Quat Quat::Inverse() const
	{
		Quat t;
		k_quat_inv(&t, this);
		return t;
	}

	inline Quat Quat::Normalize() const
	{
		Quat t;
		k_quat_norm(&t, this);
		return t;
	}

	inline Quat Quat::Exp() const
	{
		Quat t;
		k_quat_exp(&t, this);
		return t;
	}

	inline Quat Quat::Ln() const
	{
		Quat t;
		k_quat_ln(&t, this);
		return t;
	}

	inline /*static*/ Quat Quat::Interpolate(const Quat& left, const Quat& right, float f)
	{
		Quat t;
		k_quat_interpolate(&t, &left, &right, f);
		return t;
	}

	inline /*static*/ Quat Quat::Slerp(const Quat& left, const Quat& right, float f)
	{
		Quat t;
		k_quat_slerp(&t, &left, &right, f);
		return t;
	}

	inline /*static*/ Quat Quat::Squad(const Quat& q1, const Quat& q2, const Quat& q3, const Quat& q4, float f)
	{
		Quat t;
		k_quat_squad(&t, &q1, &q2, &q3, &q4, f);
		return t;
	}

	inline /*static*/ Quat Quat::Minimize(const Quat& left, const Quat& right)
	{
		return Quat(
			left.x < right.x ? left.x : right.x,
			left.y < right.y ? left.y : right.y,
			left.z < right.z ? left.z : right.z,
			left.w < right.w ? left.w : right.w);
	}

	inline /*static*/ Quat Quat::Maximize(const Quat& left, const Quat& right)
	{
		return Quat(
			left.x > right.x ? left.x : right.x,
			left.y > right.y ? left.y : right.y,
			left.z > right.z ? left.z : right.z,
			left.w > right.w ? left.w : right.w);
	}

	inline /*static*/ Quat Quat::Rotation(const Mat4& m)
	{
		Quat t;
		k_quat_rot_mat(&t, &m);
		return t;
	}

	inline /*static*/ Quat Quat::Rotation(const Vec3& v)
	{
		Quat t;
		k_quat_rot_vec(&t, &v);
		return t;
	}

	inline /*static*/ Quat Quat::Rotation(const Vec3& v, float angle)
	{
		Quat t;
		k_quat_rot_axis_vec(&t, &v, angle);
		return t;
	}

	inline /*static*/ Quat Quat::RotationX(float x)
	{
		Quat t;
		k_quat_rot_x(&t, x);
		return t;
	}

	inline /*static*/ Quat Quat::RotationY(float y)
	{
		Quat t;
		k_quat_rot_y(&t, y);
		return t;
	}

	inline /*static*/ Quat Quat::RotationZ(float z)
	{
		Quat t;
		k_quat_rot_z(&t, z);
		return t;
	}

	inline /*static*/ Quat Quat::BaryCentric(const Quat& q1, const Quat& q2, const Quat& q3, float f, float g)
	{
		Quat t;
		k_quat_bary_centric(&t, &q1, &q2, &q3, f, g);
		return t;
	}

	inline /*static*/ Quat Quat::Cross(const Quat& v1, const Quat& v2, const Quat& v3)
	{
		Quat t;
		k_quat_cross(&t, &v1, &v2, &v3);
		return t;
	}

	inline /*static*/ float Quat::Dot(const Quat& left, const Quat& right)
	{
		return left.x * right.x + left.y * right.y + left.z * right.z + left.w * right.w;
	}

	inline /*static*/ bool Quat::Equals(const Quat& left, const Quat& right, float e/*=KM_EPSILON*/)
	{
		return
			k_epsilon(left.x, right.x, e) &&
			k_epsilon(left.y, right.y, e) &&
			k_epsilon(left.z, right.z, e) &&
			k_epsilon(left.w, right.w, e);
	}

	inline /*static*/ Quat Quat::ZeroQuaternion()
	{
		return Quat(0.0f, 0.0f, 0.0f, 0.0f);
	}

	inline /*static*/ Quat Quat::IdentifyQuaternion()
	{
		return Quat(0.0f, 0.0f, 0.0f, 1.0f);
	}

#if defined(__D3DX9MATH_H__)
	inline D3DXQUATERNION& Quat::ToD3DX() const
	{
		return *(D3DXQUATERNION*)this;
	}
#endif

	// matrix
	inline Mat4::Mat4(float _11, float _12, float _13, float _14, float _21, float _22, float _23, float _24, float _31, float _32, float _33, float _34, float _41, float _42, float _43, float _44)
	{
		this->_11 = _11;
		this->_12 = _12;
		this->_13 = _13;
		this->_14 = _14;
		this->_21 = _21;
		this->_22 = _22;
		this->_23 = _23;
		this->_24 = _24;
		this->_31 = _31;
		this->_32 = _32;
		this->_33 = _33;
		this->_34 = _34;
		this->_41 = _41;
		this->_42 = _42;
		this->_43 = _43;
		this->_44 = _44;
	}

	inline Mat4::Mat4(const kMat4& right)
	{
		this->_11 = right._11;
		this->_12 = right._12;
		this->_13 = right._13;
		this->_14 = right._14;
		this->_21 = right._21;
		this->_22 = right._22;
		this->_23 = right._23;
		this->_24 = right._24;
		this->_31 = right._31;
		this->_32 = right._32;
		this->_33 = right._33;
		this->_34 = right._34;
		this->_41 = right._41;
		this->_42 = right._42;
		this->_43 = right._43;
		this->_44 = right._44;
	}

	inline float& Mat4::operator()(kint row, kint col)
	{
		return m[row][col];
	}

	inline float Mat4::operator()(kint row, kint col) const
	{
		return m[row][col];
	}

	inline Mat4& Mat4::operator+=(const Mat4& right)
	{
		_11 += right._11;
		_12 += right._12;
		_13 += right._13;
		_14 += right._14;
		_21 += right._21;
		_22 += right._22;
		_23 += right._23;
		_24 += right._24;
		_31 += right._31;
		_32 += right._32;
		_33 += right._33;
		_34 += right._34;
		_41 += right._41;
		_42 += right._42;
		_43 += right._43;
		_44 += right._44;
		return *this;
	}

	inline Mat4& Mat4::operator-=(const Mat4& right)
	{
		_11 -= right._11;
		_12 -= right._12;
		_13 -= right._13;
		_14 -= right._14;
		_21 -= right._21;
		_22 -= right._22;
		_23 -= right._23;
		_24 -= right._24;
		_31 -= right._31;
		_32 -= right._32;
		_33 -= right._33;
		_34 -= right._34;
		_41 -= right._41;
		_42 -= right._42;
		_43 -= right._43;
		_44 -= right._44;
		return *this;
	}

	inline Mat4& Mat4::operator*=(const Mat4& right)
	{
		k_mat4_mul(this, this, &right);
		return *this;
	}

	inline Mat4& Mat4::operator*=(float right)
	{
		_11 *= right;
		_12 *= right;
		_13 *= right;
		_14 *= right;
		_21 *= right;
		_22 *= right;
		_23 *= right;
		_24 *= right;
		_31 *= right;
		_32 *= right;
		_33 *= right;
		_34 *= right;
		_41 *= right;
		_42 *= right;
		_43 *= right;
		_44 *= right;
		return *this;
	}

	inline Mat4& Mat4::operator/=(float right)
	{
		_11 /= right;
		_12 /= right;
		_13 /= right;
		_14 /= right;
		_21 /= right;
		_22 /= right;
		_23 /= right;
		_24 /= right;
		_31 /= right;
		_32 /= right;
		_33 /= right;
		_34 /= right;
		_41 /= right;
		_42 /= right;
		_43 /= right;
		_44 /= right;
		return *this;
	}

	inline Mat4 Mat4::operator+() const
	{
		return *this;
	}

	inline Mat4 Mat4::operator-() const
	{
		return Mat4(
			-_11, -_12, -_13, -_14,
			-_21, -_22, -_23, -_24,
			-_31, -_32, -_33, -_34,
			-_41, -_42, -_43, -_44);
	}

	inline Mat4 Mat4::operator!() const
	{
		Mat4 t;
		k_mat4_inv(&t, NULL, this);
		return t;
	}

	inline Mat4 Mat4::operator+(const Mat4& right) const
	{
		return Mat4(
			_11 + right._11,
			_12 + right._12,
			_13 + right._13,
			_14 + right._14,
			_21 + right._21,
			_22 + right._22,
			_23 + right._23,
			_24 + right._24,
			_31 + right._31,
			_32 + right._32,
			_33 + right._33,
			_34 + right._34,
			_41 + right._41,
			_42 + right._42,
			_43 + right._43,
			_44 + right._44);
	}

	inline Mat4 Mat4::operator-(const Mat4& right) const
	{
		return Mat4(
			_11 - right._11,
			_12 - right._12,
			_13 - right._13,
			_14 - right._14,
			_21 - right._21,
			_22 - right._22,
			_23 - right._23,
			_24 - right._24,
			_31 - right._31,
			_32 - right._32,
			_33 - right._33,
			_34 - right._34,
			_41 - right._41,
			_42 - right._42,
			_43 - right._43,
			_44 - right._44);
	}

	inline Mat4 Mat4::operator*(const Mat4& right) const
	{
		Mat4 t;
		k_mat4_mul(&t, this, &right);
		return t;
	}

	inline Mat4 Mat4::operator*(float right) const
	{
		return Mat4(
			_11 * right,
			_12 * right,
			_13 * right,
			_14 * right,
			_21 * right,
			_22 * right,
			_23 * right,
			_24 * right,
			_31 * right,
			_32 * right,
			_33 * right,
			_34 * right,
			_41 * right,
			_42 * right,
			_43 * right,
			_44 * right);
	}

	inline Mat4 Mat4::operator/(float right) const
	{
		return Mat4(
			_11 / right,
			_12 / right,
			_13 / right,
			_14 / right,
			_21 / right,
			_22 / right,
			_23 / right,
			_24 / right,
			_31 / right,
			_32 / right,
			_33 / right,
			_34 / right,
			_41 / right,
			_42 / right,
			_43 / right,
			_44 / right);
	}

	inline bool Mat4::operator==(const Mat4& right) const
	{
		return memcmp(this, &right, sizeof(Mat4)) == 0;
	}

	inline bool Mat4::operator!=(const Mat4& right) const
	{
		return memcmp(this, &right, sizeof(Mat4)) != 0;
	}

	inline Mat4 operator*(float left, const Mat4& right)
	{
		return Mat4(
			left * right._11,
			left * right._12,
			left * right._13,
			left * right._14,
			left * right._21,
			left * right._22,
			left * right._23,
			left * right._24,
			left * right._31,
			left * right._32,
			left * right._33,
			left * right._34,
			left * right._41,
			left * right._42,
			left * right._43,
			left * right._44);
	}

	inline bool Mat4::IsIdentity() const
	{
		return
			_11 == 1.0f && _12 == 0.0f && _13 == 0.0f && _14 == 0.0f &&
			_21 == 0.0f && _22 == 1.0f && _23 == 0.0f && _24 == 0.0f &&
			_31 == 0.0f && _32 == 0.0f && _33 == 1.0f && _34 == 0.0f &&
			_41 == 0.0f && _42 == 0.0f && _43 == 0.0f && _44 == 1.0f;
	}

	inline float Mat4::Determinant() const
	{
		return k_mat4_det(this);
	}

	inline void Mat4::Zero()
	{
		_11 = _12 = _13 = _14 =
			_21 = _22 = _23 = _24 =
			_31 = _32 = _33 = _34 =
			_41 = _42 = _43 = _44 = 0.0f;
	}

	inline void Mat4::Identify()
	{
		_12 = _13 = _14 =
			_21 = _23 = _24 =
			_31 = _32 = _34 =
			_41 = _42 = _43 = 0.0f;
		_11 = _22 = _33 = _44 = 1.0f;
	}

	inline void Mat4::Diagonal(float v)
	{
		_12 = _13 = _14 =
			_21 = _23 = _24 =
			_31 = _32 = _34 =
			_41 = _42 = _43 = 0.0f;
		_11 = _22 = _33 = _44 = v;
	}

	inline Mat4 Mat4::Inverse() const
	{
		Mat4 t;
		k_mat4_inv(&t, NULL, this);
		return t;
	}

	inline Mat4 Mat4::Transpose() const
	{
		Mat4 t;
		k_mat4_tran(&t, this);
		return t;
	}

	inline void Mat4::ReplaceLocation(const Vec3& v)
	{
		_41 = v.x;
		_42 = v.y;
		_43 = v.z;
	}

	inline void Mat4::ReplaceLocation(float x, float y, float z)
	{
		_41 = x;
		_42 = y;
		_43 = z;
	}

	inline void Mat4::ReplaceAddLocation(const Vec3& v)
	{
		_41 += v.x;
		_42 += v.y;
		_43 += v.z;
	}

	inline void Mat4::ReplaceAddLocation(float x, float y, float z)
	{
		_41 += x;
		_42 += y;
		_43 += z;
	}

	inline void Mat4::ReplaceRotation(const Quat& q)
	{
		k_mat4_rep_rot_quat(this, &q);
	}

	inline void Mat4::ReplaceRotation(float x, float y, float z, float w)
	{
		Quat q(x, y, z, w);
		k_mat4_rep_rot_quat(this, &q);
	}

	inline void Mat4::ReplaceScaling(const Vec3& v)
	{
		_11 = v.x;
		_22 = v.y;
		_33 = v.z;
	}

	inline void Mat4::ReplaceScaling(float x, float y, float z)
	{
		_11 = x;
		_22 = y;
		_33 = z;
	}

	inline void Mat4::ReplaceLerp(const Vec3& left, const Vec3& right, float scale)
	{
		k_mat4_rep_lerp_len(this, &left, &right, scale);
	}

	inline const float* Mat4::ToPointer() const
	{
		return _m;
	}

	inline /*static*/ Mat4 Mat4::Location(const Vec3& v)
	{
		return Mat4(
			1.0f, 0.0f, 0.0f, 0.0f,
			0.0f, 1.0f, 0.0f, 0.0f,
			0.0f, 0.0f, 1.0f, 0.0f,
			v.x, v.y, v.z, 1.0f);
	}

	inline /*static*/ Mat4 Mat4::Location(float x, float y, float z)
	{
		return Mat4(
			1.0f, 0.0f, 0.0f, 0.0f,
			0.0f, 1.0f, 0.0f, 0.0f,
			0.0f, 0.0f, 1.0f, 0.0f,
			x, y, z, 1.0f);
	}

	inline /*static*/ Mat4 Mat4::Scaling(const Vec3& v)
	{
		return Mat4(
			v.x, 0.0f, 0.0f, 0.0f,
			0.0f, v.y, 0.0f, 0.0f,
			0.0f, 0.0f, v.z, 0.0f,
			0.0f, 0.0f, 0.0f, 1.0f);
	}

	inline /*static*/ Mat4 Mat4::Scaling(float x, float y, float z)
	{
		return Mat4(
			x, 0.0f, 0.0f, 0.0f,
			0.0f, y, 0.0f, 0.0f,
			0.0f, 0.0f, z, 0.0f,
			0.0f, 0.0f, 0.0f, 1.0f);
	}

	inline /*static*/ Mat4 Mat4::Scaling(float f)
	{
		return Mat4(
			f, 0.0f, 0.0f, 0.0f,
			0.0f, f, 0.0f, 0.0f,
			0.0f, 0.0f, f, 0.0f,
			0.0f, 0.0f, 0.0f, 1.0f);
	}

	inline /*static*/ Mat4 Mat4::Rotation(const Vec3& v)
	{
		Mat4 t;
		k_mat4_rot_vec(&t, &v);
		return t;
	}

	inline /*static*/ Mat4 Mat4::Rotation(const Quat& q)
	{
		Mat4 t;
		k_mat4_rot_quat(&t, &q);
		return t;
	}

	inline /*static*/ Mat4 Mat4::Rotation(float x, float y, float z)
	{
		Mat4 t;
		Vec3 v(x, y, z);
		k_mat4_rot_vec(&t, &v);
		return t;
	}

	inline /*static*/ Mat4 Mat4::Rotation(float x, float y, float z, float w)
	{
		Mat4 t;
		Quat q(x, y, z, w);
		k_mat4_rot_quat(&t, &q);
		return t;
	}

	inline /*static*/ Mat4 Mat4::RotationX(float f)
	{
		Mat4 t;
		k_mat4_rot_x(&t, f);
		return t;
	}

	inline /*static*/ Mat4 Mat4::RotationY(float f)
	{
		Mat4 t;
		k_mat4_rot_y(&t, f);
		return t;
	}

	inline /*static*/ Mat4 Mat4::RotationZ(float f)
	{
		Mat4 t;
		k_mat4_rot_z(&t, f);
		return t;
	}

	inline /*static*/ Mat4 Mat4::LookAtLH(const Vec3& eye, const Vec3& at, const Vec3& up)
	{
		Mat4 t;
		k_mat4_lookat_lh(&t, &eye, &at, &up);
		return t;
	}

	inline /*static*/ Mat4 Mat4::LookAtRH(const Vec3& eye, const Vec3& at, const Vec3& up)
	{
		Mat4 t;
		k_mat4_lookat_rh(&t, &eye, &at, &up);
		return t;
	}

	inline /*static*/ Mat4 Mat4::PerspectiveFovLH(float fov, float aspect, float znear, float zfar)
	{
		Mat4 t;
		k_mat4_perspective_lh(&t, fov, aspect, znear, zfar);
		return t;
	}

	inline /*static*/ Mat4 Mat4::PerspectiveFovRH(float fov, float aspect, float znear, float zfar)
	{
		Mat4 t;
		k_mat4_perspective_rh(&t, fov, aspect, znear, zfar);
		return t;
	}

	inline /*static*/ Mat4 Mat4::OrthoLH(float width, float height, float znear, float zfar)
	{
		Mat4 t;
		k_mat4_ortho_lh(&t, width, height, znear, zfar);
		return t;
	}

	inline /*static*/ Mat4 Mat4::OrthoRH(float width, float height, float znear, float zfar)
	{
		Mat4 t;
		k_mat4_ortho_rh(&t, width, height, znear, zfar);
		return t;
	}

	inline /*static*/ Mat4 Mat4::OrthoOffCenterLH(float l, float r, float b, float t, float zn, float zf)
	{
		Mat4 m;
		k_mat4_ortho_offcenter_lh(&m, l, r, b, t, zn, zf);
		return m;
	}

	inline /*static*/ Mat4 Mat4::OrthoOffCenterRH(float l, float r, float b, float t, float zn, float zf)
	{
		Mat4 m;
		k_mat4_ortho_offcenter_rh(&m, l, r, b, t, zn, zf);
		return m;
	}

	inline /*static*/ Mat4 Mat4::ViewPort(float x, float y, float width, float height)
	{
		Mat4 t;
		k_mat4_viewport(&t, x, y, width, height);
		return t;
	}

	inline /*static*/ Mat4 Mat4::Shadow(const Vec4& light, const Plane& plane)
	{
		Mat4 t;
		k_mat4_shadow(&t, &light, &plane);
		return t;
	}

	inline /*static*/ Mat4 Mat4::Affine(const Vec3& scl, const Vec3& rotcenter, const Quat& rot, const Vec3& loc)
	{
		Mat4 t;
		k_mat4_affine(&t, &scl, &rotcenter, &rot, &loc);
		return t;
	}

	inline /*static*/ Mat4 Mat4::Interpolate(const Mat4& left, const Mat4& right, float f)
	{
		Mat4 t;
		k_mat4_interpolate(&t, &left, &right, f);
		return t;
	}

	inline /*static*/ Mat4 Mat4::Transform(const Vec3& loc, const Quat& rot, const Vec3& scl)
	{
		Mat4 t;
		k_mat4_trfm(&t, &loc, &rot, &scl);
		return t;
	}

	inline /*static*/ Mat4 Mat4::Transform(const Vec3& loc, const Vec3& rot, const Vec3& scl)
	{
		Mat4 t;
		k_mat4_trfm_vec(&t, &loc, &rot, &scl);
		return t;
	}

	inline /*static*/ Mat4 Mat4::Transform(const TrFm& tm)
	{
		Mat4 t;
		k_mat4_trfm(&t, &tm.loc, &tm.rot, &tm.scl);
		return t;
	}

	inline /*static*/ bool Mat4::Equals(const Mat4& left, const Mat4& right)
	{
		return memcmp(&left, &right, sizeof(Mat4)) == 0;
	}

	inline /*static*/ Mat4 Mat4::ZeroMatrix()
	{
		return Mat4(
			0.0f, 0.0f, 0.0f, 0.0f,
			0.0f, 0.0f, 0.0f, 0.0f,
			0.0f, 0.0f, 0.0f, 0.0f,
			0.0f, 0.0f, 0.0f, 0.0f);
	}

	inline /*static*/ Mat4 Mat4::IdentifyMatrix()
	{
		return Mat4(
			1.0f, 0.0f, 0.0f, 0.0f,
			0.0f, 1.0f, 0.0f, 0.0f,
			0.0f, 0.0f, 1.0f, 0.0f,
			0.0f, 0.0f, 0.0f, 1.0f);
	}

#if defined(__D3DX9MATH_H__)
	inline D3DXMATRIX& Mat4::ToD3DX() const
	{
		return *(D3DXMATRIX*)this;
	}
#endif


	// point
	inline Point::Point(kint x, kint y)
	{
		this->x = x;
		this->y = y;
	}

	inline Point::Point(const kPt& right)
	{
		this->x = right.x;
		this->y = right.y;
	}

	inline void Point::Set(kint x, kint y)
	{
		this->x = x;
		this->y = y;
	}

	inline bool Point::OnPoint(kint value) const

	{
		return value >= min && value <= max;
	}

	inline void Point::SetMm(kint min, kint max)
	{
		this->min = min;
		this->max = max;
	}

	inline float Point::Aspect() const
	{
		return (float)x / (float)y;
	}

	inline Rect Point::CenterRect(kint width, kint height)
	{
		Rect rt;
		rt.SetCenter(x, y, width, height);
		return rt;
	}

#if defined(_WINDEF_)
	inline void Point::Set(const POINT& pt)
	{
		x = pt.x;
		y = pt.y;
	}
#endif

	inline Vec2 Point::ToVec2() const
	{
		return Vec2((float)x, float(y));
	}


	// rectangle
	inline Rect::Rect(kint l, kint t, kint r, kint b)
	{
		this->left = l;
		this->top = t;
		this->right = r;
		this->bottom = b;
	}

	inline Rect::Rect(const kRt& right)
	{
		this->left = right.left;
		this->top = right.top;
		this->right = right.right;
		this->bottom = right.bottom;
	}

	inline Rect::Rect(const kQd& right)
	{
		this->left = (kint)right.left;
		this->top = (kint)right.top;
		this->right = (kint)right.right;
		this->bottom = (kint)right.bottom;
	}

	inline Rect::Rect(const kPt& pos, const kPt& size)
	{
		this->left = pos.x;
		this->top = pos.y;
		this->right = pos.x + size.x;
		this->bottom = pos.y + size.y;
	}

	inline bool Rect::operator==(const Rect& right) const
	{
		return
			this->left == right.left &&
			this->top == right.top &&
			this->right == right.right &&
			this->bottom == right.bottom;
	}

	inline bool Rect::operator!=(const Rect& right) const
	{
		return
			this->left != right.left ||
			this->top != right.top ||
			this->right != right.right ||
			this->bottom != right.bottom;
	}

	inline void Rect::Zero()
	{
		left = 0;
		top = 0;
		right = 0;
		bottom = 0;
	}

	inline void Rect::Set(kint left, kint top, kint right, kint bottom)
	{
		this->left = left;
		this->top = top;
		this->right = right;
		this->bottom = bottom;
	}

#if defined(_WINDEF_)
	inline void Rect::Set(const RECT& right)
	{
		this->left = right.left;
		this->top = right.top;
		this->right = right.right;
		this->bottom = right.bottom;
	}
#endif

	inline void Rect::SetSize(kint x, kint y, kint w, kint h)
	{
		left = x;
		top = y;
		right = x + w;
		bottom = y + h;
	}

	inline void Rect::SetCenter(kint screen_width, kint screen_height, kint width, kint height)
	{
		left = (screen_width - width) / 2;
		top = (screen_height - height) / 2;
		right = left + width;
		bottom = top + height;
	}

	inline void Rect::Move(kint x, kint y)
	{
		kint w = right - left;
		kint h = bottom - top;
		left = x;
		top = y;
		right = x + w;
		bottom = y + h;
	}

	inline void Rect::Expand(kint w, kint h)
	{
		right = left + w;
		bottom = top + h;
	}

	inline Rect Rect::Inflate(kint x, kint y) const
	{
		return Rect(
			left - x,
			top - y,
			right + x,
			bottom + y);
	}

	inline Rect Rect::Deflate(kint x, kint y) const
	{
		return Rect(
			left + x,
			top + y,
			right - x,
			bottom - y);
	}

	inline Rect Rect::Offset(kint x, kint y) const
	{
		return Rect(
			left + x,
			top + y,
			right + x,
			bottom + y);
	}

	inline Rect Rect::Inflate(kint l, kint t, kint r, kint b) const
	{
		return Rect(
			left - l,
			top - t,
			right + r,
			bottom + b);
	}

	inline Rect Rect::Deflate(kint l, kint t, kint r, kint b) const
	{
		return Rect(
			left + l,
			top + t,
			right - r,
			bottom - b);
	}

	inline Rect Rect::Offset(kint l, kint t, kint r, kint b) const
	{
		return Rect(
			left + l,
			top + t,
			right + r,
			bottom + b);
	}

	inline Rect Rect::Center(kint screen_width, kint screen_height) const
	{
		int x = -(screen_width / 2) + left;
		int y = (screen_height / 2) - top;
		return Rect(x, y, x + (right - left), y - (bottom - top));
	}

	inline kint Rect::Width() const
	{
		return right - left;
	}

	inline kint Rect::Height() const
	{
		return bottom - top;
	}

	inline bool Rect::OnPoint(const Point& pt) const
	{
		return pt.x >= left && pt.x <= right && pt.y >= top && pt.y <= bottom;
	}

	inline bool Rect::OnPoint(kint x, kint y) const
	{
		return x >= left && x <= right && y >= top && y <= bottom;
	}

	inline bool Rect::Intersect(const Rect& rt) const
	{
		bool i =
			rt.left < right &&
			rt.right > left &&
			rt.top < bottom &&
			rt.bottom > top;
		return i;
	}

	inline bool Rect::Intersect(kint l, kint t, kint r, kint b) const
	{
		bool i =
			l < right &&
			r > left &&
			t < bottom &&
			b > top;
		return i;
	}

	inline bool Rect::Intersect(const Rect& r1, const Rect& r2)
	{
		bool i = (
			r2.left < r1.right &&
			r2.right > r1.left &&
			r2.top < r1.bottom &&
			r2.bottom > r1.top);

		if (!i)
		{
			left = top = right = bottom = 0;
			return false;
		}
		else
		{
			left = K_MAX(r1.left, r2.left);
			top = K_MAX(r1.top, r2.top);
			right = K_MIN(r1.right, r2.right);
			bottom = K_MIN(r1.bottom, r2.bottom);
			return true;
		}
	}

	inline float Rect::Aspect() const
	{
		return (float)Width() / (float)Height();
	}

	inline Point Rect::Location() const
	{
		return Point(left, top);
	}

	inline Point Rect::Size() const
	{
		return Point(Width(), Height());
	}

	inline Point Rect::LeftTop() const
	{
		return Point(left, top);
	}

	inline Point Rect::RightBottom() const
	{
		return Point(right, bottom);
	}

	inline Quad Rect::ToQuad() const
	{
		return Quad((float)left, (float)top, float(right), float(bottom));
	}


	// quad
	inline Quad::Quad(float l, float t, float r, float b)
	{
		this->left = l;
		this->top = t;
		this->right = r;
		this->bottom = b;
	}

	inline Quad::Quad(const kQd& right)
	{
		this->left = right.left;
		this->top = right.top;
		this->right = right.right;
		this->bottom = right.bottom;
	}

	inline Quad::Quad(const kRt& right)
	{
		this->left = (float)right.left;
		this->top = (float)right.top;
		this->right = (float)right.right;
		this->bottom = (float)right.bottom;
	}

	inline Quad::Quad(const kVec2& pos, const kVec2& size)
	{
		this->left = pos.x;
		this->top = pos.y;
		this->right = pos.x + size.x;
		this->bottom = pos.y + size.y;
	}

	inline void Quad::Zero()
	{
		left = 0;
		top = 0;
		right = 0;
		bottom = 0;
	}

	inline void Quad::Set(float left, float top, float right, float bottom)
	{
		this->left = left;
		this->top = top;
		this->right = right;
		this->bottom = bottom;
	}

	inline void Quad::Sized(float x, float y, float w, float h)
	{
		left = x;
		top = y;
		right = x + w;
		bottom = y + h;
	}

	inline Quad Quad::Inflate(float x, float y) const
	{
		return Quad(
			left - x,
			top - y,
			right + x,
			bottom + y);
	}

	inline Quad Quad::Deflate(float x, float y) const
	{
		return Quad(
			left + x,
			top + y,
			right - x,
			bottom - y);
	}

	inline Quad Quad::Offset(float x, float y) const
	{
		return Quad(
			left + x,
			top + y,
			right + x,
			bottom + y);
	}

	inline Quad Quad::Inflate(float l, float t, float r, float b) const
	{
		return Quad(
			left - l,
			top - t,
			right + r,
			bottom + b);
	}

	inline Quad Quad::Deflate(float l, float t, float r, float b) const
	{
		return Quad(
			left + l,
			top + t,
			right - r,
			bottom - b);
	}

	inline Quad Quad::Offset(float l, float t, float r, float b) const
	{
		return Quad(
			left + l,
			top + t,
			right + r,
			bottom + b);
	}

	inline Quad Quad::Center(float screen_width, float screen_height) const
	{
		float x = -(screen_width / 2) + left;
		float y = (screen_height / 2) - top;
		return Quad(x, y, x + (right - left), y - (bottom - top));
	}

	inline Quad Quad::Center(float screen_width, float screen_height, float offset_x, float offset_y) const
	{
		float x = -(screen_width / 2) + left + offset_x;
		float y = (screen_height / 2) - top + offset_y;
		return Quad(x, y, x + (right - left), y - (bottom - top));
	}

	inline float Quad::Width() const
	{
		return right - left;
	}

	inline float Quad::Height() const
	{
		return bottom - top;
	}

	inline bool Quad::OnPoint(const Vec2& pt) const
	{
		return pt.x >= left && pt.x <= right && pt.y >= top && pt.y <= bottom;
	}

	inline bool Quad::OnPoint(float x, float y) const
	{
		return x >= left && x <= right && y >= top && y <= bottom;
	}

	inline bool Quad::Intersect(const Quad& r1, const Quad& r2)
	{
		bool i = (
			r2.left < r1.right &&
			r2.right > r1.left &&
			r2.top < r1.bottom &&
			r2.bottom > r1.top);

		if (!i)
		{
			left = top = right = bottom = 0.0f;
			return false;
		}
		else
		{
			left = K_MAX(r1.left, r2.left);
			top = K_MAX(r1.top, r2.top);
			right = K_MIN(r1.right, r2.right);
			bottom = K_MIN(r1.bottom, r2.bottom);
			return true;
		}
	}

	inline Quad Quad::ConvCoord(kint sx, kint sy, kint x, kint y, kint w, kint h)
	{
		float fx = (float)sx;
		float fy = (float)sy;

		return Quad(
			(float)x / fx, 
			(float)y / fy,
			(float)(x + w) / fx,
			(float)(y + h) / fy);
	}

	inline Quad Quad::FillCoord()
	{
		return Quad(0.0f, 0.0f, 1.0f, 1.0f);
	}

	inline Quad Quad::InvCoord()
	{
		return Quad(1.0f, 1.0f, 0.0f, 0.0f);
	}

	inline float Quad::Aspect() const
	{
		return Width() / Height();
	}

	inline Vec2 Quad::Location() const
	{
		return Vec2(left, top);
	}

	inline Vec2 Quad::Size() const
	{
		return Vec2(Width(), Height());
	}

	inline Vec2 Quad::LeftTop() const
	{
		return Vec2(left, top);
	}

	inline Vec2 Quad::RightBottom() const
	{
		return Vec2(right, bottom);
	}

	inline Rect Quad::ToRect() const
	{
		return Rect((kint)left, (kint)top, (kint)right, (kint)bottom);
	}


	// color
	inline Color::Color(float r, float g, float b, float a)
	{
		this->r = r;
		this->g = g;
		this->b = b;
		this->a = a;
	}

	inline Color::Color(kuint value)
	{
		float f = 1.0f / 255.0f;
		this->b = (float)(value & 255) * f;
		value >>= 8;
		this->g = (float)(value & 255) * f;
		value >>= 8;
		this->r = (float)(value & 255) * f;
		value >>= 8;
		this->a = (float)(value & 255) * f;
		value >>= 8;
	}

	inline Color::Color(const kCu& cu)
	{
		float f = 1.0f / 255.0f;
		this->r = cu.r * f;
		this->g = cu.g * f;
		this->b = cu.b * f;
		this->a = cu.a * f;
	}

	inline Color::Color(const kCr& right)
	{
		this->r = right.r;
		this->g = right.g;
		this->b = right.b;
		this->a = right.a;
	}

	inline Color::operator kuint() const
	{
		kuint R = (this->r >= 1.0f) ? 0xff : (this->r <= 0.0f) ? 0x00 : (kuint)(this->r * 255.0f + 0.5f);
		kuint G = (this->g >= 1.0f) ? 0xff : (this->g <= 0.0f) ? 0x00 : (kuint)(this->g * 255.0f + 0.5f);
		kuint B = (this->b >= 1.0f) ? 0xff : (this->b <= 0.0f) ? 0x00 : (kuint)(this->b * 255.0f + 0.5f);
		kuint A = (this->a >= 1.0f) ? 0xff : (this->a <= 0.0f) ? 0x00 : (kuint)(this->a * 255.0f + 0.5f);
		return (A << 24) | (R << 16) | (G << 8) | B;
	}

	inline Color& Color::operator+=(const Color& right)
	{
		r += right.r;
		g += right.g;
		b += right.b;
		a += right.a;
		return *this;
	}

	inline Color& Color::operator-=(const Color& right)
	{
		r -= right.r;
		g -= right.g;
		b -= right.b;
		a -= right.a;
		return *this;
	}

	inline Color& Color::operator*=(float right)
	{
		r *= right;
		g *= right;
		b *= right;
		a *= right;
		return *this;
	}

	inline Color& Color::operator/=(float right)
	{
		r /= right;
		g /= right;
		b /= right;
		a /= right;
		return *this;
	}

	inline Color Color::operator+() const
	{
		return *this;
	}

	inline Color Color::operator+(const Color& right) const
	{
		return Color(r + right.r, g + right.g, b + right.b, a + right.a);
	}

	inline Color Color::operator-(const Color& right) const
	{
		return Color(r - right.r, g - right.g, b - right.b, a - right.a);
	}

	inline Color Color::operator*(float right) const
	{
		return Color(r * right, g * right, b * right, a * right);
	}

	inline Color Color::operator/(float right) const
	{
		return Color(r / right, g / right, b / right, a / right);
	}

	inline bool Color::operator==(const Color& right) const
	{
		return
			k_eq(r, right.r) &&
			k_eq(g, right.g) &&
			k_eq(b, right.b) &&
			k_eq(a, right.a);
	}

	inline bool Color::operator!=(const Color& right) const
	{
		return
			!k_eq(r, right.r) ||
			!k_eq(g, right.g) ||
			!k_eq(b, right.b) ||
			!k_eq(a, right.a);
	}

	inline kuint Color::ToUint() const
	{
		kuint R = (r >= 1.0f) ? 0xff : (r <= 0.0f) ? 0x00 : (kuint)(r * 255.0f + 0.5f);
		kuint G = (g >= 1.0f) ? 0xff : (g <= 0.0f) ? 0x00 : (kuint)(g * 255.0f + 0.5f);
		kuint B = (b >= 1.0f) ? 0xff : (b <= 0.0f) ? 0x00 : (kuint)(b * 255.0f + 0.5f);
		kuint A = (a >= 1.0f) ? 0xff : (a <= 0.0f) ? 0x00 : (kuint)(a * 255.0f + 0.5f);
		return (A << 24) | (R << 16) | (G << 8) | B;
	}

	inline kuint Color::ToUintSimple() const
	{
		kbyte R = (kbyte)(r * 255.0f + 0.5f);
		kbyte G = (kbyte)(g * 255.0f + 0.5f);
		kbyte B = (kbyte)(b * 255.0f + 0.5f);
		kbyte A = (kbyte)(a * 255.0f + 0.5f);
		return ((kuint)A << 24) | ((kuint)R << 16) | ((kuint)G << 8) | (kuint)B;
	}

	inline const float* Color::ToPointer() const
	{
		return (float*)this;
	}

	inline void Color::Set(float r, float g, float b, float a/*=1.0f*/)
	{
		this->r = r;
		this->g = g;
		this->b = b;
		this->a = a;
	}

	inline void Color::Set(kuint n)
	{
		float f = 1.0f / 255.0f;
		this->b = (float)(n & 255) * f;
		n >>= 8;
		this->g = (float)(n & 255) * f;
		n >>= 8;
		this->r = (float)(n & 255) * f;
		n >>= 8;
		this->a = (float)(n & 255) * f;
		n >>= 8;
	}

	inline Color Color::Negative() const
	{
		return Color(1.0f - r, 1.0f - g, 1.0f - b, a);
	}

	inline Color Color::Contrast(float s) const
	{
		return Color(
			0.5f + s * (r - 0.5f),
			0.5f + s * (g - 0.5f),
			0.5f + s * (b - 0.5f),
			a);
	}

	inline Color Color::Saturation(float s) const
	{
		float f = r * 0.2125f + g * 0.7154f + b * 0.0721f;
		return Color(
			f + s * (r - f),
			f + s * (g - f),
			f + s * (b - f),
			a);
	}

	inline Color Color::Brighten(float s) const
	{
		Color c(r * s, g * s, b * s, a);

		if (c.r > 1.0f) c.r = 1.0f;

		if (c.g > 1.0f) c.g = 1.0f;

		if (c.b > 1.0f) c.b = 1.0f;

		return c;
	}

	inline /*static*/ Color Color::Interpolate(const Color& left, const Color& right, float s)
	{
		float f = 1.0f - s;
		return Color(
			right.r * f + left.r * s,
			right.g * f + left.g * s,
			right.b * f + left.b * s,
			right.a * f + left.a * s);
	}

	inline /*static*/ Color Color::Lerp(const Color& left, const Color& right, float s)
	{
		return Color(
			left.r + s * (right.r - left.r),
			left.g + s * (right.g - left.g),
			left.b + s * (right.b - left.b),
			left.a + s * (right.a - left.a));
	}

	inline /*static*/ Color Color::Modulate(const Color& left, const Color& right)
	{
		return Color(
			left.r * right.r,
			left.g * right.g,
			left.b * right.b,
			left.a * right.a);
	}

	inline /*static*/ Color Color::Minimize(const Color& left, const Color& right)
	{
		return Color(
			left.r < right.r ? left.r : right.r,
			left.g < right.g ? left.g : right.g,
			left.b < right.b ? left.b : right.b,
			left.a < right.a ? left.a : right.a);
	}

	inline /*static*/ Color Color::Maximize(const Color& left, const Color& right)
	{
		return Color(
			left.r > right.r ? left.r : right.r,
			left.g > right.g ? left.g : right.g,
			left.b > right.b ? left.b : right.b,
			left.a > right.a ? left.a : right.a);
	}

	inline /*static*/ bool Color::Equals(const Color& left, const Color& right, float e/*=KM_EPSILON*/)
	{
		return
			k_epsilon(left.r, right.r, e) &&
			k_epsilon(left.g, right.g, e) &&
			k_epsilon(left.b, right.b, e) &&
			k_epsilon(left.a, right.a, e);
	}

	// color value
	inline ColorValue::ColorValue(kbyte r, kbyte g, kbyte b, kbyte a)
	{
		this->r = r;
		this->g = g;
		this->b = b;
		this->a = a;
	}

	inline ColorValue::ColorValue(kuint value)
	{
		((kUcu*)this)->v = value;
	}

	inline ColorValue::ColorValue(const kCr& cr)
	{
		r = (kbyte)k_rint(cr.r * 255.0f);
		g = (kbyte)k_rint(cr.g * 255.0f);
		b = (kbyte)k_rint(cr.b * 255.0f);
		a = (kbyte)k_rint(cr.a * 255.0f);
	}

	inline ColorValue::ColorValue(const kCu& right)
	{
		((kUcu*)this)->v = ((kUcu&)right).v;
	}

	inline ColorValue::operator kuint() const
	{
		return ((kUcu*)this)->v;
	}

	inline ColorValue& ColorValue::operator+=(const ColorValue& right)
	{
		r += right.r;
		g += right.g;
		b += right.b;
		a += right.a;
		return *this;
	}

	inline ColorValue& ColorValue::operator-=(const ColorValue& right)
	{
		r -= right.r;
		g -= right.g;
		b -= right.b;
		a -= right.a;
		return *this;
	}

	inline ColorValue& ColorValue::operator*=(float right)
	{
		r = (kbyte)k_rint(r * right);
		g = (kbyte)k_rint(g * right);
		b = (kbyte)k_rint(b * right);
		a = (kbyte)k_rint(a * right);
		return *this;
	}

	inline ColorValue& ColorValue::operator/=(float right)
	{
		r = (kbyte)k_rint(r / right);
		g = (kbyte)k_rint(g / right);
		b = (kbyte)k_rint(b / right);
		a = (kbyte)k_rint(a / right);
		return *this;
	}

	inline ColorValue ColorValue::operator+() const
	{
		return *this;
	}

	inline ColorValue ColorValue::operator+(const ColorValue& right) const
	{
		return ColorValue(r + right.r, g + right.g, b + right.b, a + right.a);
	}

	inline ColorValue ColorValue::operator-(const ColorValue& right) const
	{
		return ColorValue(r - right.r, g - right.g, b - right.b, a - right.a);
	}

	inline ColorValue ColorValue::operator*(float right) const
	{
		return ColorValue(
			(kbyte)k_rint(r * right),
			(kbyte)k_rint(g * right),
			(kbyte)k_rint(b * right),
			(kbyte)k_rint(a * right));
	}

	inline ColorValue ColorValue::operator/(float right) const
	{
		return ColorValue(
			(kbyte)k_rint(r / right),
			(kbyte)k_rint(g / right),
			(kbyte)k_rint(b / right),
			(kbyte)k_rint(a / right));
	}

	inline bool ColorValue::operator==(const ColorValue& right) const
	{
		return
			r == right.r &&
			g == right.g &&
			b == right.b &&
			a == right.a;
	}

	inline bool ColorValue::operator!=(const ColorValue& right) const
	{
		return
			r != right.r ||
			g != right.g ||
			b != right.b ||
			a != right.a;
	}

	inline kuint ColorValue::ToUint() const
	{
		return ((kUcu*)this)->v;
	}

	inline kuint ColorValue::ToBgra() const
	{
		kvint& v = (kvint&)((kUcu*)this)->v;
		return K_MAKECOLOR(v.b.d, v.b.a, v.b.b, v.b.c);
	}

	inline const kbyte* ColorValue::ToPointer() const
	{
		return (const kbyte*)&((kUcu*)this)->v;
	}

	inline void ColorValue::Set(kbyte r, kbyte g, kbyte b, kbyte a)
	{
		this->r = r;
		this->g = g;
		this->b = b;
		this->a = a;
	}

	inline void ColorValue::Set(kuint n)
	{
		((kUcu*)this)->v = n;
	}

	inline ColorValue ColorValue::Negative() const
	{
		return ColorValue(255 - r, 255 - g, 255 - b, a);
	}

	inline ColorValue ColorValue::Contrast(float s) const
	{
		return ColorValue(
			(kbyte)(k_rint(s * (r - 128)) * 255.0f),
			(kbyte)(k_rint(s * (g - 128)) * 255.0f),
			(kbyte)(k_rint(s * (b - 128)) * 255.0f),
			a);
	}

	inline ColorValue ColorValue::Saturation(float s) const
	{
		float c = r * 0.2125f + g * 0.7154f + b * 0.0721f;
		return ColorValue(
			(kbyte)k_rint(c + s * (r - c)),
			(kbyte)k_rint(c + s * (g - c)),
			(kbyte)k_rint(c + s * (b - c)),
			a);
	}

	inline ColorValue ColorValue::Brighten(float s) const
	{
		return ColorValue(
			(kbyte)k_rint(r * s),
			(kbyte)k_rint(g * s),
			(kbyte)k_rint(b * s),
			a);
	}

	inline /*static*/ ColorValue ColorValue::Interpolate(const ColorValue& left, const ColorValue& right, float s)
	{
		float f = 1.0f - s;
		return ColorValue(
			(kbyte)k_rint(right.r * f + left.r * s),
			(kbyte)k_rint(right.g * f + left.g * s),
			(kbyte)k_rint(right.b * f + left.b * s),
			(kbyte)k_rint(right.a * f + left.a * s));
	}

	inline /*static*/ ColorValue ColorValue::Lerp(const ColorValue& left, const ColorValue& right, float s)
	{
		return ColorValue(
			(kbyte)k_rint(left.r + s * (right.r - left.r)),
			(kbyte)k_rint(left.g + s * (right.g - left.g)),
			(kbyte)k_rint(left.b + s * (right.b - left.b)),
			(kbyte)k_rint(left.a + s * (right.a - left.a)));
	}

	inline /*static*/ ColorValue ColorValue::Modulate(const ColorValue& left, const ColorValue& right)
	{
		return ColorValue(
			left.r * right.r,
			left.g * right.g,
			left.b * right.b,
			left.a * right.a);
	}

	inline /*static*/ ColorValue ColorValue::Minimize(const ColorValue& left, const ColorValue& right)
	{
		return ColorValue(
			left.r < right.r ? left.r : right.r,
			left.g < right.g ? left.g : right.g,
			left.b < right.b ? left.b : right.b,
			left.a < right.a ? left.a : right.a);
	}

	inline /*static*/ ColorValue ColorValue::Maximize(const ColorValue& left, const ColorValue& right)
	{
		return ColorValue(
			left.r > right.r ? left.r : right.r,
			left.g > right.g ? left.g : right.g,
			left.b > right.b ? left.b : right.b,
			left.a > right.a ? left.a : right.a);
	}


	// plane
	inline Plane::Plane(float a, float b, float c, float d/*=1.0f*/)
	{
		this->a = a;
		this->b = b;
		this->c = c;
		this->d = d;
	}

	inline Plane::Plane(const kPln& right)
	{
		this->a = right.a;
		this->b = right.b;
		this->c = right.c;
		this->d = right.d;
	}

	inline float Plane::DotCoord(const Vec3& v) const
	{
		return a * v.x + b * v.y + c * v.z + d;
	}

	inline float Plane::Distance(const Vec3& v) const
	{
		return Vec3::Dot(v, *(Vec3*)this) + d;
	}

	inline kint Plane::RelationPoint(const Vec3& v) const
	{
		float f = Vec3::Dot(*(Vec3*)this, v) + d;

		if (f < -KM_EPSILON)
			return -1;  // back

		if (f > KM_EPSILON)
			return 1;   // front

		return 0;       // on
	}

	inline void Plane::Identify()
	{
		a = 0.0f;
		b = 0.0f;
		c = 0.0f;
		d = 1.0f;
	}

	inline void Plane::Set(float a, float b, float c, float d)
	{
		this->a = a;
		this->b = b;
		this->c = c;
		this->d = d;
	}

	inline void Plane::Set(const Vec3& v, float d/*=1.0f*/)
	{
		this->a = v.x;
		this->b = v.y;
		this->c = v.z;
		this->d = d;
	}

	inline Plane Plane::Normalize() const
	{
		Plane t;
		k_pln_norm(&t, this);
		return t;
	}

	inline Plane Plane::ReverseNormalize() const
	{
		Plane t;
		k_pln_revnorm(&t, this);
		return t;
	}

	inline bool Plane::TestIntersectPlane(Vec3* loc, Vec3* dir, const Plane& pl) const
	{
		return k_pln_test_intersect_pln(this, loc, dir, &pl) != 0;
	}

	inline bool Plane::IntersectPlane(const Plane& o1, const Plane& o2) const
	{
		return k_pln_intersect_plane(this, &o1, &o2) != 0;
	}

	inline float Plane::IntersectLine(const Vec3& v1, const Vec3& v2) const
	{
		return k_pln_intersect_line(this, &v1, &v2) != 0;
	}

	inline /*static*/ Plane Plane::Transform(const Plane& left, const Mat4& right)
	{
		Plane t;
		k_pln_trfm(&t, &left, &right);
		return t;
	}

	inline /*static*/ Plane Plane::FromPoints(const Vec3& v1, const Vec3& v2, const Vec3& v3)
	{
		Plane t;
		k_pln_from_points(&t, &v1, &v2, &v3);
		return t;
	}

	inline /*static*/ Plane Plane::FromPointNormal(const Vec3& v, const Vec3& n)
	{
		Plane t;
		k_pln_from_point_norm(&t, &v, &n);
		return t;
	}


	// line3
	inline Line3::Line3(float bx, float by, float bz, float ex, float ey, float ez)
	{
		begin.x = bx;
		begin.y = by;
		begin.z = bz;
		end.x = ex;
		end.y = ey;
		end.z = ez;
	}

	inline Line3::Line3(const kVec3& begin, const kVec3& end)
	{
		this->begin = begin;
		this->end = end;
	}

	inline Line3::Line3(const kLn3& right)
	{
		this->begin = right.begin;
		this->end = right.end;
	}

	inline float Line3::LengthSq() const
	{
		return Vec3::DistanceSq((const Vec3&)begin, (const Vec3&)end);
	}

	inline float Line3::Length() const
	{
		return Vec3::Distance((const Vec3&)begin, (const Vec3&)end);
	}

	inline Vec3 Line3::Center() const
	{
		return ((Vec3&)begin + (Vec3&)end) * 0.5f;
	}

	inline Vec3 Line3::Vector() const
	{
		return (Vec3&)end - (Vec3&)begin;
	}

	inline Vec3 Line3::ClosestPoint(const Vec3& v) const
	{
		Vec3 t;
		k_vec3_cpt_line(&t, this, &v);
		return t;
	}

	inline bool Line3::BetweenPoint(const Vec3& v) const
	{
		return k_vec3_between(&v, &begin, &end) != 0;
	}

	inline void Line3::Set(float bx, float by, float bz, float ex, float ey, float ez)
	{
		begin.x = bx;
		begin.y = by;
		begin.z = bz;
		end.x = ex;
		end.y = ey;
		end.z = ez;
	}

	inline void Line3::Set(const Vec3& begin, const Vec3& end)
	{
		this->begin = begin;
		this->end = end;
	}

	inline bool Line3::IntersectSphere(const Vec3& org, float radius, float* dist/*=0*/) const
	{
		return k_ln3_intersect_sphere(this, &org, radius, dist) != 0;
	}

	inline const Vec3& Line3::Begin() const
	{
		return (Vec3&)this->begin;
	}

	inline const Vec3& Line3::End() const
	{
		return (Vec3&)this->begin;
	}

	inline Vec3& Line3::Begin()
	{
		return (Vec3&)this->begin;
	}

	inline Vec3& Line3::End()
	{
		return (Vec3&)this->end;
	}


	// trfm
	inline TrFm::TrFm(const kVec3& loc, const kQuat& rot, const kVec3& scl)
	{
		this->loc = loc;
		this->rot = rot;
		this->scl = scl;
	}

	inline void TrFm::Identify()
	{
		loc.Identify();
		rot.Identify();
		scl.Identify();
	}


	// vech2
	inline VecH2::VecH2(const kVec2& right)
	{
		this->x = k_ftohf(right.x);
		this->y = k_ftohf(right.y);
	}

	inline VecH2::VecH2(float x, float y)
	{
		this->x = k_ftohf(x);
		this->y = k_ftohf(y);
	}

	inline Vec2 VecH2::ToVec2() const
	{
		return Vec2(k_hftof(x), k_hftof(y));
	}

	inline void VecH2::Set(float x, float y)
	{
		this->x = k_ftohf(x);
		this->y = k_ftohf(y);
	}

	inline bool VecH2::Equals(const VecH2& left, const VecH2& right)
	{
		return left.x == right.x && left.y == right.y;
	}


	// vech3
	inline VecH3::VecH3(const kVec3& right)
	{
		this->x = k_ftohf(right.x);
		this->y = k_ftohf(right.y);
		this->z = k_ftohf(right.z);
	}

	inline VecH3::VecH3(float x, float y, float z)
	{
		this->x = k_ftohf(x);
		this->y = k_ftohf(y);
		this->z = k_ftohf(z);
	}

	inline Vec3 VecH3::ToVec3() const
	{
		return Vec3(k_hftof(x), k_hftof(y), k_hftof(z));
	}

	inline void VecH3::Set(float x, float y, float z)
	{
		this->x = k_ftohf(x);
		this->y = k_ftohf(y);
		this->z = k_ftohf(z);
	}

	inline bool VecH3::Equals(const VecH3& left, const VecH3& right)
	{
		return left.x == right.x && left.y == right.y && left.z == right.z;
	}


	// vech4
	inline VecH4::VecH4(const kVec4& right)
	{
		this->x = k_ftohf(right.x);
		this->y = k_ftohf(right.y);
		this->z = k_ftohf(right.z);
		this->w = k_ftohf(right.w);
	}

	inline VecH4::VecH4(float x, float y, float z, float w)
	{
		this->x = k_ftohf(x);
		this->y = k_ftohf(y);
		this->z = k_ftohf(z);
		this->w = k_ftohf(w);
	}

	inline Vec4 VecH4::ToVec4() const
	{
		return Vec4(k_hftof(x), k_hftof(y), k_hftof(z), k_hftof(w));
	}

	inline void VecH4::Set(float x, float y, float z, float w)
	{
		this->x = k_ftohf(x);
		this->y = k_ftohf(y);
		this->z = k_ftohf(z);
		this->w = k_ftohf(w);
	}

	inline bool VecH4::Equals(const VecH4& left, const VecH4& right)
	{
		return left.x == right.x && left.y == right.y && left.z == right.z && left.w == right.w;
	}


	// color blend
	inline BlendColor::BlendColor()
		: adv(0.0f), loop(false), dir(1)
	{
		color[1].Set(1.0f, 1.0f, 1.0f);
		color[2].Set(0.0f, 0.0f, 0.0f, 0.4f);
	}

	inline BlendColor::BlendColor(const kCr& c1, const kCr& c2, bool loop)
		: adv(0.0f), loop(loop), dir(1)
	{
		color[1] = Color(c1);
		color[2] = Color(c2);
	}

	inline void BlendColor::Reset(bool loop)
	{
		this->adv = 0.0f;
		this->dir = 1;
		this->loop = loop;
	}

	inline void BlendColor::Reset(const Color& c1, const Color& c2, bool loop)
	{
		this->color[1] = c1;
		this->color[2] = c2;
		this->adv = 0.0f;
		this->dir = 1;
		this->loop = loop;
	}

	inline void BlendColor::Update(float a, float speed)
	{
		switch (dir)
		{
			case 1:
				adv += a * speed;

				if (adv > 1.0f)
				{
					adv = 1.0f;
					dir = !loop ? 0 : 2;
				}

				break;

			case 2:
				adv += a * speed;

				if (adv < 0.0f)
				{
					adv = 0.0f;
					dir = !loop ? 0 : 1;
				}

				break;

			default:
				return;
		}

		color[0] = Color::Interpolate(color[1], color[2], adv);
	}

	inline const Color& BlendColor::Value()
	{
		return color[0];
	}

	// colors
	namespace Colors
	{
		K_ANY_CONST kCr White = {1.0f, 1.0f, 1.0f, 1.0f};
		K_ANY_CONST kCr Black = {0.0f, 0.0f, 0.0f, 1.0f};
		K_ANY_CONST kCr Blue = {0.0f, 0.0f, 1.0f, 1.0f};
		K_ANY_CONST kCr Green = {0.0f, 1.0f, 0.0f, 1.0f};
		K_ANY_CONST kCr Red = {1.0f, 0.0f, 0.0f, 1.0f};
		K_ANY_CONST kCr Yellow = {1.0f, 1.0f, 0.0f, 1.0f};
		K_ANY_CONST kCr Cyan = {0.0f, 1.0f, 1.0f, 1.0f};
		K_ANY_CONST kCr Magenta = {1.0f, 0.0f, 1.0f, 1.0f};
		K_ANY_CONST kCr Transparent = {0.0f, 0.0f, 0.0f, 0.0f};
	}

	// color values
	namespace ColorValues
	{
		K_ANY_CONST kCu White = {255, 255, 255, 255};
		K_ANY_CONST kCu Black = {0, 0, 0, 255};
		K_ANY_CONST kCu Blue = {255, 0, 0, 255};
		K_ANY_CONST kCu Green = {0, 255, 0, 255};
		K_ANY_CONST kCu Red = {0, 0, 255, 255};
		K_ANY_CONST kCu Yellow = {0, 255, 255, 255};
		K_ANY_CONST kCu Cyan = {255, 255, 0, 255};
		K_ANY_CONST kCu Magenta = {255, 0, 255, 255};
		K_ANY_CONST kCu Transparent = {0, 0, 0, 0};
	}

	// coords
	namespace Coords
	{
		K_ANY_CONST kQd Fill = {0.0f, 0.0f, 1.0f, 1.0f};
		K_ANY_CONST kQd InvFill = {1.0f, 1.0f, 0.0f, 0.0f};
	}

	// matrices
	namespace Matrices
	{
		K_ANY_CONST kMat4 Zero  = {0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f};
		K_ANY_CONST kMat4 Identity = {1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f};
	}

}   // tpl
#endif	// __cplusplus

#if _MSC_VER
#pragma warning(pop)
#endif

#endif  // __SBMATH_H__
